aa-buybackprogram 3.0.0b3__tar.gz → 3.1.0__tar.gz
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_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/PKG-INFO +33 -4
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/README.md +32 -3
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/__init__.py +1 -1
- aa_buybackprogram-3.1.0/buybackprogram/admin.py +194 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/forms.py +68 -4
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/helpers.py +1 -2
- aa_buybackprogram-3.1.0/buybackprogram/migrations/0019_program_tracking_prefill_reverseprogram_stock_source_and_more.py +123 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/models.py +360 -94
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/notification.py +1 -1
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/tasks.py +47 -18
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/contract_details.html +13 -2
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/index.html +45 -5
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/stats/tabs/finished.html +9 -7
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/stats/tabs/outstanding.html +9 -7
- aa_buybackprogram-3.1.0/buybackprogram/templates/buybackprogram/partials/stats/tabs/untracked.html +48 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/reverse_program/reverse_calculate.html +197 -104
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/reverse_program/reverse_index.html +45 -5
- aa_buybackprogram-3.1.0/buybackprogram/templates/buybackprogram/reverse_program/reverse_program_add.html +258 -0
- aa_buybackprogram-3.1.0/buybackprogram/templates/buybackprogram/reverse_program/reverse_program_edit.html +259 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/reverse_program/reverse_program_stats.html +129 -4
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/reverse_program/reverse_stats.html +74 -5
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/tests/test_helpers.py +18 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/tests/test_reverse_buyback.py +13 -4
- aa_buybackprogram-3.1.0/buybackprogram/tests/test_tasks.py +94 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/urls.py +20 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/views/calculate.py +21 -2
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/views/programs.py +58 -4
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/views/stats.py +130 -1
- aa_buybackprogram-3.0.0b3/buybackprogram/admin.py +0 -62
- aa_buybackprogram-3.0.0b3/buybackprogram/templates/buybackprogram/partials/stats/tabs/untracked.html +0 -55
- aa_buybackprogram-3.0.0b3/buybackprogram/templates/buybackprogram/reverse_program/reverse_program_add.html +0 -59
- aa_buybackprogram-3.0.0b3/buybackprogram/templates/buybackprogram/reverse_program/reverse_program_edit.html +0 -64
- aa_buybackprogram-3.0.0b3/buybackprogram/tests/test_data_migrations.log +0 -2
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/LICENSE +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/app_settings.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/apps.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/auth_hooks.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/constants.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/decorators.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/management/__init__.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/management/commands/__init__.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/management/commands/buybackprogram_generate_test_data.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/management/commands/buybackprogram_link_contracts.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/management/commands/buybackprogram_load_data.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/management/commands/buybackprogram_load_prices.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/management/commands/generate_dummy_data.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/migrations/0001_initial.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/migrations/0002_contractnotification.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/migrations/0003_statics_performance_increase.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/migrations/0004_auto_20220323_1331.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/migrations/0005_program_compression_price_dencity_modifier.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/migrations/0006_program_bonds_npc_price_and_more.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/migrations/0007_program_expiration.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/migrations/0008_alter_general_options_alter_program_refining_rate.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/migrations/0009_contract_location_name.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/migrations/0010_contract_no_tracking_alter_tracking_tracking_number.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/migrations/0011_delete_duplicated_contracts.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/migrations/0012_make_contract_id_unique.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/migrations/0013_program_discord_show_item_list.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/migrations/0014_program_price_type.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/migrations/0015_faq_contractnotification_header_and_more.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/migrations/0016_alter_program_compression_price_dencity_modifier.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/migrations/0017_alter_contract_price_alter_contract_volume_and_more.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/migrations/0018_structurenamecache_alter_general_options_and_more.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/migrations/__init__.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/notes.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/providers.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/static/buybackprogram/css/billboards_dark.css +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/static/buybackprogram/css/billboards_light.css +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/static/buybackprogram/css/style_dark.css +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/static/buybackprogram/css/style_light.css +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/static/buybackprogram/images/help.png +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/static/buybackprogram/js/autocomplete.js +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/static/buybackprogram/js/bootstrap-autocomplete.min.js +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/swagger.json +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/base.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/bundles/buybackprogram-css-light.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/faq.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/leaderboards.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/location_add.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/page.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/base/menu-management.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/base/menu-reverse-management.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/base/menu-reverse.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/base/menu.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/calculate/accepted_locations.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/calculate/calculation_success.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/calculate/contract_settings.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/calculate/invoice.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/calculate/item_details.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/details/accepted-locations.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/details/contract-info.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/details/invoice.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/details/tabs/contract-items.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/details/tabs/original-items.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/details/tabs/tabs-navigation.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/details/warning.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/stats/summary.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/stats/tabs/tabs-navigation.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/stats/tabs/wallet_overview.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/partials/stats/warning.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/performance.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/program_add.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/program_calculate.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/program_edit.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/program_edit_item.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/program_edit_marketgroup.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/program_edit_static_price.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/program_edit_watchlist.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/program_special_taxes.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/reverse_program/reverse_contract_details.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/stats.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templates/buybackprogram/user_settings.html +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templatetags/__init__.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templatetags/bs_tab_color_class.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templatetags/help_icons.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templatetags/price_formats.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/templatetags/program_settings.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/tests/__init__.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/tests/test_data_migrations.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/tests/test_models.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/tests/test_reverse_contract_notifications.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/tests/test_views.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/tests/testdata/__init__.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/tests/testdata/create_eveuniverse.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/tests/testdata/eveuniverse.json +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/tests/testdata/factories.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/tests/testdata/load_eveuniverse.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/utils.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/views/__init__.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/views/common.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/buybackprogram/views/special_taxes.py +0 -0
- {aa_buybackprogram-3.0.0b3 → aa_buybackprogram-3.1.0}/pyproject.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aa-buybackprogram
|
|
3
|
-
Version: 3.0
|
|
3
|
+
Version: 3.1.0
|
|
4
4
|
Summary: Buyback program plugin app for Alliance Auth.
|
|
5
5
|
Author-email: Ikarus Cesaille <contact@eve-linknet.com>
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -39,6 +39,7 @@ An Alliance Auth app for creating buyback programs and to allow users calculate
|
|
|
39
39
|
- [Features](#features)
|
|
40
40
|
- [Installation](#installation)
|
|
41
41
|
- [Program Settings](#program-settings)
|
|
42
|
+
- [Troubleshooting](#troubleshooting)
|
|
42
43
|
- [Change Log](CHANGELOG.md)
|
|
43
44
|
|
|
44
45
|
## Images
|
|
@@ -165,7 +166,7 @@ Buyback program requires a few periodic tasks to operate and update its data.
|
|
|
165
166
|
|
|
166
167
|
Buybackprogram is designed to use locally stored prices to speed up the price calculations. It is important that you have the price update task in your periodic tasks so that your prices will update.
|
|
167
168
|
|
|
168
|
-
By adding the following lines in your `local.py` setting file the program will update the stored item prices at midnight. This same task is also responsible for maintenance tasks such as removing unlinked tracking objects. It will also check for any new contracts and update the statistics page with them every 30 minutes:
|
|
169
|
+
By adding the following lines in your `local.py` setting file the program will update the stored item prices at midnight. This same task is also responsible for maintenance tasks such as removing unlinked tracking objects, including reverse buyback requests that were never followed through with an actual contract (which releases the stock they had reserved). It will also check for any new contracts and update the statistics page with them every 30 minutes:
|
|
169
170
|
|
|
170
171
|
```python
|
|
171
172
|
# Buybackprogram price updates, updates prices at midnight
|
|
@@ -207,14 +208,14 @@ Name | Description | Default | Options
|
|
|
207
208
|
BUYBACKPROGRAM_ENABLE_REVERSE_BUYBACK | Enable or disable the reverse buyback feature entirely. When disabled the menu item will not appear. | True | `True`, `False`
|
|
208
209
|
BUYBACKPROGRAM_DISALLOW_CONTRACTS_WITH_ANY_DISALLOWED_ITEMS | Prevents price calculations if there are any disallowed items in the parsed list | False | `True`, `False`
|
|
209
210
|
BUYBACKPROGRAM_SHOW_LOCATION_COUNT | How many locations we will show on buyback index page before we change it to a pop-up show all locations button | 4 | Integer
|
|
210
|
-
BUYBACKPROGRAM_TRACKING_PREFILL |
|
|
211
|
+
BUYBACKPROGRAM_TRACKING_PREFILL | Default prefill tag used at the start of tracking numbers for your contracts. Individual buyback and reverse buyback programs can override this from their program settings (Tracking prefill tag), e.g. to separate ore and manufacturing buybacks in reports. | aa-bbp. | Free text input
|
|
211
212
|
BUYBACKPROGRAM_PRICE_SOURCE_ID | Station ID for fetching base prices. Supports IDs listed on [Fuzzwork API](https://market.fuzzwork.co.uk/api/). Does not work with Janice API!| 60003760 | See ID list
|
|
212
213
|
BUYBACKPROGRAM_PRICE_SOURCE_NAME | Display name of your price source. Has no effect on the actual price fetch which uses the ID. | Jita | Free text input
|
|
213
214
|
BUYBACKPROGRAM_PRICE_AGE_WARNING_LIMIT | Limit in hours when an item price is considered as outdated | 48
|
|
214
215
|
BUYBACKPROGRAM_PRICE_METHOD | By default Fuzzwork API will be used for pricing, if this is set to "Janice" then the Janice API will be used. | Fuzzwork | `Fuzzwork`, `Janice`
|
|
215
216
|
BUYBACKPROGRAM_PRICE_INSTANT_PRICES | On default we use top 5% average prices. Set to `true` to change to instant prices | False | `False`, `True`
|
|
216
217
|
BUYBACKPROGRAM_PRICE_JANICE_API_KEY | The API key to access Janice API. | `null` | `G9KwKq3465588VPd6747t95Zh94q3W2E`
|
|
217
|
-
BUYBACKPROGRAM_UNUSED_TRACKING_PURGE_LIMIT | Time limit to remove unlinked tracking objects from the database. Set to 0 to never purge any tracking objects. | 48 | Any number in hours
|
|
218
|
+
BUYBACKPROGRAM_UNUSED_TRACKING_PURGE_LIMIT | Time limit to remove unlinked tracking objects (both normal and reverse buyback requests) from the database. Purging an unlinked reverse buyback request also releases the hangar stock it had reserved. Set to 0 to never purge any tracking objects. | 48 | Any number in hours
|
|
218
219
|
BUYBACKPROGRAM_TRACK_PREFILL_CONTRACTS | Determines if we will track and store contracts that starts with the prefill phrase but do not have any actual tracking hits in database | True | `True`, `False`
|
|
219
220
|
BUYBACKPROGRAM_RESTRICT_TRACKING_DETAILS | When True, only the contract issuer and managers can view tracking detail pages via direct URL. Set to False to allow any authenticated basic_access user to view any tracking detail. | False | `True`, `False`
|
|
220
221
|
|
|
@@ -513,6 +514,20 @@ If ticked, contracts will be issued from the manager's corporation.
|
|
|
513
514
|
##### Location
|
|
514
515
|
The structure where stock is held and contracts will be created. The structure ID must be set on the location for hangar sync to work.
|
|
515
516
|
|
|
517
|
+
##### Stock Source
|
|
518
|
+
Choose where the program's stock comes from:
|
|
519
|
+
|
|
520
|
+
- **Whole hangar division** — everything in the selected Hangar Division at the program locations is for sale.
|
|
521
|
+
- **Selected containers only** — only the contents of the chosen containers are for sale. Use this when you cannot dedicate an entire division to buyback. Containers must be assembled and sitting directly in a hangar division at one of the program locations; nested containers are not supported. Give containers a name ingame so they are easy to pick from the list.
|
|
522
|
+
|
|
523
|
+
Containers are discovered during the hangar sync, so on a new manager the container list is empty until the first sync has run. Click **Refresh Stock** and reload the page if the list is empty. If a selected container is repackaged or moved away from the program locations it disappears from the program's stock and a warning is written to the log.
|
|
524
|
+
|
|
525
|
+
##### Hangar Division
|
|
526
|
+
The corporation hangar division to sell from. Only used when the stock source is a whole hangar division.
|
|
527
|
+
|
|
528
|
+
##### Containers
|
|
529
|
+
The containers to sell from. Only used when the stock source is selected containers.
|
|
530
|
+
|
|
516
531
|
##### Price Type
|
|
517
532
|
The base price type used to value items. Default: Sell.
|
|
518
533
|
|
|
@@ -535,3 +550,17 @@ Once your program is created, click **Refresh Stock** in the management menu to
|
|
|
535
550
|
|
|
536
551
|
Players navigate to **Reverse Buyback**, click **Buy** on a program, paste a list of items they want, and submit. The calculator checks availability against current stock and generates a price and tracking number. The player then waits for the owner to create a contract to them using the tracking number as the contract title.
|
|
537
552
|
|
|
553
|
+
|
|
554
|
+
## Troubleshooting
|
|
555
|
+
|
|
556
|
+
### Contract updates stop running after a worker restart
|
|
557
|
+
|
|
558
|
+
Symptom: the log shows `Starting all contract updates` and `Updating contracts for <owner>` for each owner, but no `Fetching all contracts for ...` line follows and no contracts are linked.
|
|
559
|
+
|
|
560
|
+
Cause: each owner's contract update runs as a run-once task. If a worker is restarted while the task is running (for example right after applying migrations), the lock is never released and every following run is silently skipped until the lock expires. The lock is stored in the Django cache and expires after `BUYBACKPROGRAM_TASKS_TIME_LIMIT` seconds (2 hours by default).
|
|
561
|
+
|
|
562
|
+
To clear the locks immediately:
|
|
563
|
+
|
|
564
|
+
```bash
|
|
565
|
+
redis-cli -n 1 --scan --pattern "*qo_buybackprogram*" | xargs -r redis-cli -n 1 del
|
|
566
|
+
|
|
@@ -13,6 +13,7 @@ An Alliance Auth app for creating buyback programs and to allow users calculate
|
|
|
13
13
|
- [Features](#features)
|
|
14
14
|
- [Installation](#installation)
|
|
15
15
|
- [Program Settings](#program-settings)
|
|
16
|
+
- [Troubleshooting](#troubleshooting)
|
|
16
17
|
- [Change Log](CHANGELOG.md)
|
|
17
18
|
|
|
18
19
|
## Images
|
|
@@ -139,7 +140,7 @@ Buyback program requires a few periodic tasks to operate and update its data.
|
|
|
139
140
|
|
|
140
141
|
Buybackprogram is designed to use locally stored prices to speed up the price calculations. It is important that you have the price update task in your periodic tasks so that your prices will update.
|
|
141
142
|
|
|
142
|
-
By adding the following lines in your `local.py` setting file the program will update the stored item prices at midnight. This same task is also responsible for maintenance tasks such as removing unlinked tracking objects. It will also check for any new contracts and update the statistics page with them every 30 minutes:
|
|
143
|
+
By adding the following lines in your `local.py` setting file the program will update the stored item prices at midnight. This same task is also responsible for maintenance tasks such as removing unlinked tracking objects, including reverse buyback requests that were never followed through with an actual contract (which releases the stock they had reserved). It will also check for any new contracts and update the statistics page with them every 30 minutes:
|
|
143
144
|
|
|
144
145
|
```python
|
|
145
146
|
# Buybackprogram price updates, updates prices at midnight
|
|
@@ -181,14 +182,14 @@ Name | Description | Default | Options
|
|
|
181
182
|
BUYBACKPROGRAM_ENABLE_REVERSE_BUYBACK | Enable or disable the reverse buyback feature entirely. When disabled the menu item will not appear. | True | `True`, `False`
|
|
182
183
|
BUYBACKPROGRAM_DISALLOW_CONTRACTS_WITH_ANY_DISALLOWED_ITEMS | Prevents price calculations if there are any disallowed items in the parsed list | False | `True`, `False`
|
|
183
184
|
BUYBACKPROGRAM_SHOW_LOCATION_COUNT | How many locations we will show on buyback index page before we change it to a pop-up show all locations button | 4 | Integer
|
|
184
|
-
BUYBACKPROGRAM_TRACKING_PREFILL |
|
|
185
|
+
BUYBACKPROGRAM_TRACKING_PREFILL | Default prefill tag used at the start of tracking numbers for your contracts. Individual buyback and reverse buyback programs can override this from their program settings (Tracking prefill tag), e.g. to separate ore and manufacturing buybacks in reports. | aa-bbp. | Free text input
|
|
185
186
|
BUYBACKPROGRAM_PRICE_SOURCE_ID | Station ID for fetching base prices. Supports IDs listed on [Fuzzwork API](https://market.fuzzwork.co.uk/api/). Does not work with Janice API!| 60003760 | See ID list
|
|
186
187
|
BUYBACKPROGRAM_PRICE_SOURCE_NAME | Display name of your price source. Has no effect on the actual price fetch which uses the ID. | Jita | Free text input
|
|
187
188
|
BUYBACKPROGRAM_PRICE_AGE_WARNING_LIMIT | Limit in hours when an item price is considered as outdated | 48
|
|
188
189
|
BUYBACKPROGRAM_PRICE_METHOD | By default Fuzzwork API will be used for pricing, if this is set to "Janice" then the Janice API will be used. | Fuzzwork | `Fuzzwork`, `Janice`
|
|
189
190
|
BUYBACKPROGRAM_PRICE_INSTANT_PRICES | On default we use top 5% average prices. Set to `true` to change to instant prices | False | `False`, `True`
|
|
190
191
|
BUYBACKPROGRAM_PRICE_JANICE_API_KEY | The API key to access Janice API. | `null` | `G9KwKq3465588VPd6747t95Zh94q3W2E`
|
|
191
|
-
BUYBACKPROGRAM_UNUSED_TRACKING_PURGE_LIMIT | Time limit to remove unlinked tracking objects from the database. Set to 0 to never purge any tracking objects. | 48 | Any number in hours
|
|
192
|
+
BUYBACKPROGRAM_UNUSED_TRACKING_PURGE_LIMIT | Time limit to remove unlinked tracking objects (both normal and reverse buyback requests) from the database. Purging an unlinked reverse buyback request also releases the hangar stock it had reserved. Set to 0 to never purge any tracking objects. | 48 | Any number in hours
|
|
192
193
|
BUYBACKPROGRAM_TRACK_PREFILL_CONTRACTS | Determines if we will track and store contracts that starts with the prefill phrase but do not have any actual tracking hits in database | True | `True`, `False`
|
|
193
194
|
BUYBACKPROGRAM_RESTRICT_TRACKING_DETAILS | When True, only the contract issuer and managers can view tracking detail pages via direct URL. Set to False to allow any authenticated basic_access user to view any tracking detail. | False | `True`, `False`
|
|
194
195
|
|
|
@@ -487,6 +488,20 @@ If ticked, contracts will be issued from the manager's corporation.
|
|
|
487
488
|
##### Location
|
|
488
489
|
The structure where stock is held and contracts will be created. The structure ID must be set on the location for hangar sync to work.
|
|
489
490
|
|
|
491
|
+
##### Stock Source
|
|
492
|
+
Choose where the program's stock comes from:
|
|
493
|
+
|
|
494
|
+
- **Whole hangar division** — everything in the selected Hangar Division at the program locations is for sale.
|
|
495
|
+
- **Selected containers only** — only the contents of the chosen containers are for sale. Use this when you cannot dedicate an entire division to buyback. Containers must be assembled and sitting directly in a hangar division at one of the program locations; nested containers are not supported. Give containers a name ingame so they are easy to pick from the list.
|
|
496
|
+
|
|
497
|
+
Containers are discovered during the hangar sync, so on a new manager the container list is empty until the first sync has run. Click **Refresh Stock** and reload the page if the list is empty. If a selected container is repackaged or moved away from the program locations it disappears from the program's stock and a warning is written to the log.
|
|
498
|
+
|
|
499
|
+
##### Hangar Division
|
|
500
|
+
The corporation hangar division to sell from. Only used when the stock source is a whole hangar division.
|
|
501
|
+
|
|
502
|
+
##### Containers
|
|
503
|
+
The containers to sell from. Only used when the stock source is selected containers.
|
|
504
|
+
|
|
490
505
|
##### Price Type
|
|
491
506
|
The base price type used to value items. Default: Sell.
|
|
492
507
|
|
|
@@ -508,3 +523,17 @@ Once your program is created, click **Refresh Stock** in the management menu to
|
|
|
508
523
|
#### How it works for players
|
|
509
524
|
|
|
510
525
|
Players navigate to **Reverse Buyback**, click **Buy** on a program, paste a list of items they want, and submit. The calculator checks availability against current stock and generates a price and tracking number. The player then waits for the owner to create a contract to them using the tracking number as the contract title.
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
## Troubleshooting
|
|
529
|
+
|
|
530
|
+
### Contract updates stop running after a worker restart
|
|
531
|
+
|
|
532
|
+
Symptom: the log shows `Starting all contract updates` and `Updating contracts for <owner>` for each owner, but no `Fetching all contracts for ...` line follows and no contracts are linked.
|
|
533
|
+
|
|
534
|
+
Cause: each owner's contract update runs as a run-once task. If a worker is restarted while the task is running (for example right after applying migrations), the lock is never released and every following run is silently skipped until the lock expires. The lock is stored in the Django cache and expires after `BUYBACKPROGRAM_TASKS_TIME_LIMIT` seconds (2 hours by default).
|
|
535
|
+
|
|
536
|
+
To clear the locks immediately:
|
|
537
|
+
|
|
538
|
+
```bash
|
|
539
|
+
redis-cli -n 1 --scan --pattern "*qo_buybackprogram*" | xargs -r redis-cli -n 1 del
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
from django.contrib import admin
|
|
2
|
+
from django.db.models import Exists, OuterRef
|
|
3
|
+
|
|
4
|
+
from .models import (
|
|
5
|
+
Contract,
|
|
6
|
+
Faq,
|
|
7
|
+
HangarContainer,
|
|
8
|
+
HangarDivision,
|
|
9
|
+
HangarStock,
|
|
10
|
+
Location,
|
|
11
|
+
Owner,
|
|
12
|
+
Program,
|
|
13
|
+
ReverseProgram,
|
|
14
|
+
ReverseTracking,
|
|
15
|
+
ReverseTrackingItem,
|
|
16
|
+
StaticItemPrice,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
# Register your models here.
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ProgramAdmin(admin.ModelAdmin):
|
|
23
|
+
model = Program
|
|
24
|
+
|
|
25
|
+
list_display = (
|
|
26
|
+
"owner",
|
|
27
|
+
"_location",
|
|
28
|
+
"is_corporation",
|
|
29
|
+
"hauling_fuel_cost",
|
|
30
|
+
"tax",
|
|
31
|
+
"refining_rate",
|
|
32
|
+
"price_dencity_modifier",
|
|
33
|
+
"allow_all_items",
|
|
34
|
+
"use_refined_value",
|
|
35
|
+
"use_compressed_value",
|
|
36
|
+
"use_raw_ore_value",
|
|
37
|
+
"allow_unpacked_items",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
@classmethod
|
|
41
|
+
def _location(cls, obj):
|
|
42
|
+
names = [x.name for x in obj.location.all().order_by("name")]
|
|
43
|
+
|
|
44
|
+
if names:
|
|
45
|
+
return ", ".join(names)
|
|
46
|
+
else:
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
_location.short_description = "Location"
|
|
50
|
+
_location.admin_order_field = "location__name"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class FaqAdmin(admin.ModelAdmin):
|
|
54
|
+
model = Program
|
|
55
|
+
|
|
56
|
+
list_display = (
|
|
57
|
+
"header",
|
|
58
|
+
"body",
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class ContractTypeFilter(admin.SimpleListFilter):
|
|
63
|
+
title = "contract type"
|
|
64
|
+
parameter_name = "contract_type"
|
|
65
|
+
|
|
66
|
+
def lookups(self, request, model_admin):
|
|
67
|
+
return (
|
|
68
|
+
("reverse", "Reverse buyback"),
|
|
69
|
+
("normal", "Normal buyback"),
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
def queryset(self, request, queryset):
|
|
73
|
+
if self.value() == "reverse":
|
|
74
|
+
return queryset.filter(reversetracking__isnull=False).distinct()
|
|
75
|
+
if self.value() == "normal":
|
|
76
|
+
return queryset.filter(reversetracking__isnull=True)
|
|
77
|
+
return None
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@admin.register(Contract)
|
|
81
|
+
class ContractAdmin(admin.ModelAdmin):
|
|
82
|
+
list_display = (
|
|
83
|
+
"contract_id",
|
|
84
|
+
"status",
|
|
85
|
+
"price",
|
|
86
|
+
"date_issued",
|
|
87
|
+
"location_name",
|
|
88
|
+
"_is_reverse",
|
|
89
|
+
"no_tracking",
|
|
90
|
+
)
|
|
91
|
+
list_filter = (ContractTypeFilter, "status")
|
|
92
|
+
search_fields = ("contract_id", "title", "location_name")
|
|
93
|
+
|
|
94
|
+
def get_queryset(self, request):
|
|
95
|
+
return (
|
|
96
|
+
super()
|
|
97
|
+
.get_queryset(request)
|
|
98
|
+
.annotate(
|
|
99
|
+
is_reverse=Exists(
|
|
100
|
+
ReverseTracking.objects.filter(contract=OuterRef("pk"))
|
|
101
|
+
)
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
@admin.display(description="Reverse", boolean=True, ordering="is_reverse")
|
|
106
|
+
def _is_reverse(self, obj):
|
|
107
|
+
return obj.is_reverse
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@admin.register(StaticItemPrice)
|
|
111
|
+
class StaticItemPriceAdmin(admin.ModelAdmin):
|
|
112
|
+
list_display = ("program", "eve_type", "price")
|
|
113
|
+
search_fields = ("program__name", "eve_type__name")
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@admin.register(ReverseProgram)
|
|
117
|
+
class ReverseProgramAdmin(admin.ModelAdmin):
|
|
118
|
+
list_display = (
|
|
119
|
+
"name",
|
|
120
|
+
"owner",
|
|
121
|
+
"is_corporation",
|
|
122
|
+
"stock_source",
|
|
123
|
+
"price_type",
|
|
124
|
+
"markup",
|
|
125
|
+
"is_public",
|
|
126
|
+
)
|
|
127
|
+
list_filter = ("stock_source",)
|
|
128
|
+
search_fields = ("name",)
|
|
129
|
+
filter_horizontal = ("containers",)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
class ReverseTrackingItemInline(admin.TabularInline):
|
|
133
|
+
model = ReverseTrackingItem
|
|
134
|
+
extra = 0
|
|
135
|
+
raw_id_fields = ("eve_type",)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
@admin.register(ReverseTracking)
|
|
139
|
+
class ReverseTrackingAdmin(admin.ModelAdmin):
|
|
140
|
+
list_display = (
|
|
141
|
+
"tracking_number",
|
|
142
|
+
"program",
|
|
143
|
+
"issuer_user",
|
|
144
|
+
"net_price",
|
|
145
|
+
"created_at",
|
|
146
|
+
"_contract_status",
|
|
147
|
+
)
|
|
148
|
+
list_filter = (("contract", admin.EmptyFieldListFilter), "program")
|
|
149
|
+
search_fields = ("tracking_number",)
|
|
150
|
+
inlines = [ReverseTrackingItemInline]
|
|
151
|
+
|
|
152
|
+
@admin.display(description="Contract status")
|
|
153
|
+
def _contract_status(self, obj):
|
|
154
|
+
if obj.contract is None:
|
|
155
|
+
return "unlinked"
|
|
156
|
+
return obj.contract.status
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@admin.register(HangarStock)
|
|
160
|
+
class HangarStockAdmin(admin.ModelAdmin):
|
|
161
|
+
list_display = ("program", "eve_type", "quantity", "updated_at")
|
|
162
|
+
search_fields = ("program__name", "eve_type__name")
|
|
163
|
+
raw_id_fields = ("eve_type",)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
@admin.register(HangarDivision)
|
|
167
|
+
class HangarDivisionAdmin(admin.ModelAdmin):
|
|
168
|
+
list_display = ("name", "owner", "division_id", "location_flag", "updated_at")
|
|
169
|
+
search_fields = ("name",)
|
|
170
|
+
list_filter = ("owner",)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
@admin.register(HangarContainer)
|
|
174
|
+
class HangarContainerAdmin(admin.ModelAdmin):
|
|
175
|
+
list_display = (
|
|
176
|
+
"name",
|
|
177
|
+
"type_name",
|
|
178
|
+
"owner",
|
|
179
|
+
"item_id",
|
|
180
|
+
"structure_id",
|
|
181
|
+
"location_flag",
|
|
182
|
+
"updated_at",
|
|
183
|
+
)
|
|
184
|
+
search_fields = ("name", "item_id")
|
|
185
|
+
list_filter = ("owner", "location_flag")
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
admin.site.register(Program, ProgramAdmin)
|
|
189
|
+
|
|
190
|
+
admin.site.register(Owner)
|
|
191
|
+
|
|
192
|
+
admin.site.register(Location)
|
|
193
|
+
|
|
194
|
+
admin.site.register(Faq, FaqAdmin)
|
|
@@ -3,7 +3,9 @@ from django.core.validators import MaxValueValidator, MinValueValidator
|
|
|
3
3
|
from django.utils.translation import gettext as _
|
|
4
4
|
from eveuniverse.models import EveGroup, EveMarketGroup, EveSolarSystem, EveType
|
|
5
5
|
|
|
6
|
+
from buybackprogram.app_settings import BUYBACKPROGRAM_TRACKING_PREFILL
|
|
6
7
|
from buybackprogram.models import (
|
|
8
|
+
HangarContainer,
|
|
7
9
|
HangarDivision,
|
|
8
10
|
Location,
|
|
9
11
|
Owner,
|
|
@@ -30,6 +32,9 @@ class ProgramForm(forms.ModelForm):
|
|
|
30
32
|
self.user = kwargs.pop("user", None)
|
|
31
33
|
|
|
32
34
|
super(ProgramForm, self).__init__(*args, **kwargs)
|
|
35
|
+
self.fields["tracking_prefill"].widget.attrs["placeholder"] = (
|
|
36
|
+
"%s (global default)" % BUYBACKPROGRAM_TRACKING_PREFILL
|
|
37
|
+
)
|
|
33
38
|
self.fields["owner"].queryset = Owner.objects.filter(user=self.user)
|
|
34
39
|
self.fields["location"].queryset = Location.objects.filter(
|
|
35
40
|
owner__user=self.user
|
|
@@ -257,6 +262,9 @@ class ReverseProgramForm(forms.ModelForm):
|
|
|
257
262
|
"is_public": "Public program",
|
|
258
263
|
"is_corporation": "Use corporation as contract issuer",
|
|
259
264
|
}
|
|
265
|
+
widgets = {
|
|
266
|
+
"stock_source": forms.RadioSelect,
|
|
267
|
+
}
|
|
260
268
|
|
|
261
269
|
def __init__(self, *args, **kwargs):
|
|
262
270
|
self.user = kwargs.pop("user", None)
|
|
@@ -267,17 +275,73 @@ class ReverseProgramForm(forms.ModelForm):
|
|
|
267
275
|
)
|
|
268
276
|
|
|
269
277
|
if is_admin:
|
|
270
|
-
|
|
278
|
+
owners = Owner.objects.all()
|
|
271
279
|
self.fields["location"].queryset = Location.objects.all()
|
|
272
|
-
self.fields["hangar_division"].queryset = HangarDivision.objects.all()
|
|
273
280
|
else:
|
|
274
|
-
|
|
281
|
+
owners = Owner.objects.filter(user=self.user)
|
|
275
282
|
self.fields["location"].queryset = Location.objects.filter(
|
|
276
283
|
owner__user=self.user
|
|
277
284
|
)
|
|
285
|
+
self.fields["owner"].queryset = owners
|
|
286
|
+
|
|
287
|
+
# Hangar divisions and containers are only ever offered for the
|
|
288
|
+
# selected manager, so one manager's hangar layout is never rendered
|
|
289
|
+
# for another. Before a manager is picked the lists are empty and the
|
|
290
|
+
# page fills them via the autocomplete endpoints.
|
|
291
|
+
owner_id = self.data.get("owner") if self.is_bound else None
|
|
292
|
+
if not owner_id and self.instance.pk:
|
|
293
|
+
owner_id = self.instance.owner_id
|
|
294
|
+
|
|
295
|
+
if self.is_bound:
|
|
296
|
+
location_ids = self.data.getlist("location")
|
|
297
|
+
elif self.instance.pk:
|
|
298
|
+
location_ids = list(self.instance.location.values_list("pk", flat=True))
|
|
299
|
+
else:
|
|
300
|
+
location_ids = []
|
|
301
|
+
|
|
302
|
+
if owner_id and owners.filter(pk=owner_id).exists():
|
|
278
303
|
self.fields["hangar_division"].queryset = HangarDivision.objects.filter(
|
|
279
|
-
|
|
304
|
+
owner_id=owner_id
|
|
305
|
+
)
|
|
306
|
+
# Only containers sitting at one of the program's locations can
|
|
307
|
+
# ever supply stock, so nothing else is offered or accepted
|
|
308
|
+
structure_ids = Location.objects.filter(
|
|
309
|
+
pk__in=location_ids, structure_id__isnull=False
|
|
310
|
+
).values_list("structure_id", flat=True)
|
|
311
|
+
self.fields["containers"].queryset = HangarContainer.objects.filter(
|
|
312
|
+
owner_id=owner_id, structure_id__in=structure_ids
|
|
280
313
|
)
|
|
314
|
+
else:
|
|
315
|
+
self.fields["hangar_division"].queryset = HangarDivision.objects.none()
|
|
316
|
+
self.fields["containers"].queryset = HangarContainer.objects.none()
|
|
317
|
+
|
|
318
|
+
def clean(self):
|
|
319
|
+
cleaned_data = super().clean()
|
|
320
|
+
stock_source = cleaned_data.get("stock_source")
|
|
321
|
+
owner = cleaned_data.get("owner")
|
|
322
|
+
containers = cleaned_data.get("containers")
|
|
323
|
+
|
|
324
|
+
if stock_source == ReverseProgram.StockSource.CONTAINERS:
|
|
325
|
+
locations = cleaned_data.get("location")
|
|
326
|
+
if (
|
|
327
|
+
locations is not None
|
|
328
|
+
and not locations.filter(structure_id__isnull=False).exists()
|
|
329
|
+
):
|
|
330
|
+
self.add_error(
|
|
331
|
+
"location",
|
|
332
|
+
"Selected containers only needs at least one location with a structure ID set; containers are matched by structure.",
|
|
333
|
+
)
|
|
334
|
+
if not containers:
|
|
335
|
+
self.add_error(
|
|
336
|
+
"containers",
|
|
337
|
+
"Select at least one container, or change the stock source to a whole hangar division.",
|
|
338
|
+
)
|
|
339
|
+
elif owner and containers.exclude(owner=owner).exists():
|
|
340
|
+
self.add_error(
|
|
341
|
+
"containers", "All containers must belong to the selected manager."
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
return cleaned_data
|
|
281
345
|
|
|
282
346
|
|
|
283
347
|
class ReverseCalculatorForm(forms.Form):
|
|
@@ -16,7 +16,6 @@ from buybackprogram.app_settings import (
|
|
|
16
16
|
BUYBACKPROGRAM_PRICE_JANICE_API_KEY,
|
|
17
17
|
BUYBACKPROGRAM_PRICE_METHOD,
|
|
18
18
|
BUYBACKPROGRAM_PRICE_SOURCE_ID,
|
|
19
|
-
BUYBACKPROGRAM_TRACKING_PREFILL,
|
|
20
19
|
)
|
|
21
20
|
from buybackprogram.constants import (
|
|
22
21
|
BLUE_LOOT_TYPE_IDS,
|
|
@@ -1257,7 +1256,7 @@ def get_tracking_number(
|
|
|
1257
1256
|
last_id = 0
|
|
1258
1257
|
|
|
1259
1258
|
tracking_number = (
|
|
1260
|
-
|
|
1259
|
+
program.get_tracking_prefill()
|
|
1261
1260
|
+ "-"
|
|
1262
1261
|
+ str(last_id)
|
|
1263
1262
|
+ "-"
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Generated by Django 5.2.15 on 2026-09-14 04:26
|
|
2
|
+
|
|
3
|
+
import django.core.validators
|
|
4
|
+
import django.db.models.deletion
|
|
5
|
+
from django.db import migrations, models
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Migration(migrations.Migration):
|
|
9
|
+
dependencies = [
|
|
10
|
+
("buybackprogram", "0018_structurenamecache_alter_general_options_and_more"),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
operations = [
|
|
14
|
+
migrations.AddField(
|
|
15
|
+
model_name="program",
|
|
16
|
+
name="tracking_prefill",
|
|
17
|
+
field=models.CharField(
|
|
18
|
+
blank=True,
|
|
19
|
+
default="",
|
|
20
|
+
help_text="Optional tag used as the start of tracking numbers for this program, for example aa-bbp-ore. Leave empty to use the global BUYBACKPROGRAM_TRACKING_PREFILL setting. Only letters, numbers, dots, dashes and underscores.",
|
|
21
|
+
max_length=16,
|
|
22
|
+
validators=[
|
|
23
|
+
django.core.validators.RegexValidator(
|
|
24
|
+
"^[A-Za-z0-9._-]*$",
|
|
25
|
+
"Only letters, numbers, dots, dashes and underscores are allowed.",
|
|
26
|
+
)
|
|
27
|
+
],
|
|
28
|
+
verbose_name="Tracking prefill tag",
|
|
29
|
+
),
|
|
30
|
+
),
|
|
31
|
+
migrations.AddField(
|
|
32
|
+
model_name="reverseprogram",
|
|
33
|
+
name="stock_source",
|
|
34
|
+
field=models.CharField(
|
|
35
|
+
choices=[
|
|
36
|
+
("division", "Whole hangar division"),
|
|
37
|
+
("containers", "Selected containers only"),
|
|
38
|
+
],
|
|
39
|
+
default="division",
|
|
40
|
+
help_text="Sell everything in a hangar division, or only the contents of specific containers at the program locations.",
|
|
41
|
+
max_length=10,
|
|
42
|
+
verbose_name="Stock source",
|
|
43
|
+
),
|
|
44
|
+
),
|
|
45
|
+
migrations.AddField(
|
|
46
|
+
model_name="reverseprogram",
|
|
47
|
+
name="tracking_prefill",
|
|
48
|
+
field=models.CharField(
|
|
49
|
+
blank=True,
|
|
50
|
+
default="",
|
|
51
|
+
help_text="Optional tag used as the start of tracking numbers for this program. Leave empty to use the global BUYBACKPROGRAM_TRACKING_PREFILL setting. Only letters, numbers, dots, dashes and underscores.",
|
|
52
|
+
max_length=16,
|
|
53
|
+
validators=[
|
|
54
|
+
django.core.validators.RegexValidator(
|
|
55
|
+
"^[A-Za-z0-9._-]*$",
|
|
56
|
+
"Only letters, numbers, dots, dashes and underscores are allowed.",
|
|
57
|
+
)
|
|
58
|
+
],
|
|
59
|
+
verbose_name="Tracking prefill tag",
|
|
60
|
+
),
|
|
61
|
+
),
|
|
62
|
+
migrations.AlterField(
|
|
63
|
+
model_name="reverseprogram",
|
|
64
|
+
name="hangar_division",
|
|
65
|
+
field=models.ForeignKey(
|
|
66
|
+
blank=True,
|
|
67
|
+
help_text="The corporation hangar division where stock is stored. Used when stock source is a whole hangar division.",
|
|
68
|
+
null=True,
|
|
69
|
+
on_delete=django.db.models.deletion.SET_NULL,
|
|
70
|
+
to="buybackprogram.hangardivision",
|
|
71
|
+
),
|
|
72
|
+
),
|
|
73
|
+
migrations.CreateModel(
|
|
74
|
+
name="HangarContainer",
|
|
75
|
+
fields=[
|
|
76
|
+
(
|
|
77
|
+
"id",
|
|
78
|
+
models.AutoField(
|
|
79
|
+
auto_created=True,
|
|
80
|
+
primary_key=True,
|
|
81
|
+
serialize=False,
|
|
82
|
+
verbose_name="ID",
|
|
83
|
+
),
|
|
84
|
+
),
|
|
85
|
+
(
|
|
86
|
+
"item_id",
|
|
87
|
+
models.BigIntegerField(
|
|
88
|
+
help_text="ESI asset item id of the container"
|
|
89
|
+
),
|
|
90
|
+
),
|
|
91
|
+
("name", models.CharField(max_length=128)),
|
|
92
|
+
("type_name", models.CharField(blank=True, default="", max_length=128)),
|
|
93
|
+
("structure_id", models.BigIntegerField(blank=True, null=True)),
|
|
94
|
+
(
|
|
95
|
+
"location_flag",
|
|
96
|
+
models.CharField(blank=True, default="", max_length=32),
|
|
97
|
+
),
|
|
98
|
+
("updated_at", models.DateTimeField(auto_now=True)),
|
|
99
|
+
(
|
|
100
|
+
"owner",
|
|
101
|
+
models.ForeignKey(
|
|
102
|
+
on_delete=django.db.models.deletion.CASCADE,
|
|
103
|
+
related_name="containers",
|
|
104
|
+
to="buybackprogram.owner",
|
|
105
|
+
),
|
|
106
|
+
),
|
|
107
|
+
],
|
|
108
|
+
options={
|
|
109
|
+
"default_permissions": (),
|
|
110
|
+
"unique_together": {("owner", "item_id")},
|
|
111
|
+
},
|
|
112
|
+
),
|
|
113
|
+
migrations.AddField(
|
|
114
|
+
model_name="reverseprogram",
|
|
115
|
+
name="containers",
|
|
116
|
+
field=models.ManyToManyField(
|
|
117
|
+
blank=True,
|
|
118
|
+
help_text="Containers whose contents are sold. Used when stock source is selected containers. Containers appear here after the first hangar sync; name them ingame to make them easy to identify.",
|
|
119
|
+
related_name="+",
|
|
120
|
+
to="buybackprogram.hangarcontainer",
|
|
121
|
+
),
|
|
122
|
+
),
|
|
123
|
+
]
|