* change linked orderpositions to many-to-many
* Update media views to list ops
* return last op as fallback for linked_orderposition
* add multi-op to export
* update media-API
* fix media-view filter
* update control media forms
* fix API orders
* fix API orders matching media
* remove cached_property linked_orderposition - keep only in API
* fix media-issue signal
* adapt checkin API for multiple orderpositions
* remove unneeded comment
* fix create/update logging
* fix tests
* fix more tests
* fix code style
* add label to reusablemedium
* fix migration NOT NULL
* fix tests
* update docs
* clarify docs updating multiple linked_orderpositions
* clarify docs
* no need to prefetch linked_orderpositions
* improve readability
* select_related order instead prefetch
* add filter based on op.valid_from/until
* rename secret to claim_token
* Update docs for claim_token
* unifiy deprecated style
* Update reusablemedia.rst
* Update reusablemedia.rst
* Update reusablemedia.rst
* fix missing claim_token in serializer
* fix flake8
* add add_to_reusable_medium to order-serializer
* fix tests regarding claim_token
* fix flake8
* Clarify docs
* list ops comma-separated in export
* Add test for order-API add_to_reusable_medium
* fix linked_orderpositions filter in checkinrpc
* add test
* Add help-text
* fix multi-op media filter
* fix flake8
* improve check
* Fix sorting of reusable media type in overview
* Add copy and qr button to reusable medium detail view
* Rebase against origin/master
* Add logentrytype reusable_medium.linked_orderposition.removed
* add missing label_from_instance for SafeOrderPositionMultipleChoiceField
* add tests for create with linked_orderposition
* API add test for fallback-values in medium patch
* fix flake8
* Fix indentation
* fix migrations numbering
* fix test
* unify qutation marks
* fix flake8
* micro-improve linked_op-removal-logging
* simplify filter instead of annotate/get
* Do not translate API-errors
Co-authored-by: Raphael Michel <michel@pretix.eu>
* Fix typos in doc
Co-authored-by: Raphael Michel <mail@raphaelmichel.de>
* Update versionchanged in docs
Co-authored-by: Raphael Michel <michel@pretix.eu>
* Change log to always added not changed
* Add test for checkinrpc for ops out of timerang or canceled
* improve tests mixing ops from different organizers
* Fix logging of changed order_positions
* properly log added/removed when using UI
* refactor logging code
* unify logging adding/removing ops via API
* fix flake8
* remove unnecessary prefetch as already prefetched
* optimize fetching ops
* combine addon match and time-based validity match
* fix combined valid and product check
* re-number migrations
* Apply suggestion from @raphaelm
Co-authored-by: Raphael Michel <michel@pretix.eu>
* fix flake8
* New attempt at logic
* Improve op_candidate-selection for error message if no op matches check-in
* Fix typo
* fix valid_from start time being included
* use the datetime parameter for the comparison time so that the simulator works too
---------
Co-authored-by: Maximilian Richt <richt@pretix.eu>
Co-authored-by: Martin Gross <gross@rami.io>
Co-authored-by: Raphael Michel <michel@pretix.eu>
Co-authored-by: Raphael Michel <mail@raphaelmichel.de>
The old code relied on the `Voucher.redeemed` value obtained *before*
the lock was taken, not afterwards.
The change in services/orders.py is functionally pointless, but it makes
the pattern of "fill availability only after lock" clearer and might
avoid introducing similar bugs in the future.
* Tax rounding: Allow to apply only for B2B (Z#23220106)
Most effective in combination with #5807
* Update src/pretix/base/settings.py
Co-authored-by: Richard Schreiber <schreiber@pretix.eu>
---------
Co-authored-by: Richard Schreiber <schreiber@pretix.eu>
* Order changes: Do not allow to double-book add-ons
* tests
* Update src/pretix/presale/templates/pretixpresale/event/fragment_addon_choice.html
Co-authored-by: Richard Schreiber <schreiber@pretix.eu>
---------
Co-authored-by: Richard Schreiber <schreiber@pretix.eu>
* OrderChangeManager: Add support for custom operations
* OrderChangeManager: Add callback to AddPosition operation
This is also meant as a way to fix#5548
* Refs #5557: Checkstyle fix
* Refs #5557: Added tests
* Refs #5557: Changes requested in the PR review
* Refs #5557: Fix error in previous merge conflict
* Refs #5557: PR review
* Allow to round taxes on order-level
* Rename get_cart_total
* Persist rounding mode with order
* Add general docs
* Order creation API
* Update fee algorithm
* Rounding on payment method change
* Round when splitting order
* Fix failing tests
* Add settings page
* Add tests
* Replace algorithm
* Add test case for currency rounding
* Improve order change
* Update flowchart
* Update discount logic (more hypothetical, we don't store rounding on cart positions atm)
* Rename internal method
* Fix typo
* Update help text
* Apply suggestions from code review
Co-authored-by: luelista <weller@rami.io>
* Order rounding refactor (#5571)
* Add RoundingCorrectionMixin providing before-rounding-values as properties
* Use gross_price_before_rounding in more places
* Update doc/development/algorithms/pricing.rst
Co-authored-by: Martin Gross <gross@rami.io>
* Allow to override on perform_order
* Rebase migration
* Fix event cancellation
---------
Co-authored-by: luelista <weller@rami.io>
Co-authored-by: Martin Gross <gross@rami.io>
* datasync: add immediate parameter to enqueue_order
* interactive argument for order_placed signal
The ``interactive`` argument specifies whether the order was
placed interactively, by a customer (as opposed to via a bulk
import or the REST API).
* use bulk=True instead of interactive=False to mark bulk imports
* Flexible invoice transmission
* UI work
* Add peppol and output
* API support
* Profile integration
* Simplify form for individuals
* Remove sent_to_customer usage
* more steps
* Revert "Bank transfer: Allow to send the invoice direclty to the accounting department (#2975)"
This reverts commit cea6c340be.
* minor fixes
* Fixes after rebase
* update stati
* Backend view
* Transmit and show status
* status, retransmission
* API retransmission
* More fields
* API docs
* Plugin docs
* Update migration
* Add missing license headers
* Remove dead code, fix current tests
* Run isort
* Update regex
* Rebase migration
* Fix migration
* Add tests, fix bugs
* Rebase migration
* Apply suggestion from @luelista
Co-authored-by: luelista <weller@rami.io>
* Apply suggestion from @luelista
Co-authored-by: luelista <weller@rami.io>
* Apply suggestion from @luelista
Co-authored-by: luelista <weller@rami.io>
* Apply suggestion from @luelista
Co-authored-by: luelista <weller@rami.io>
* Apply suggestion from @luelista
Co-authored-by: luelista <weller@rami.io>
* Make migration reversible
* Add TransmissionType.enforce_transmission
* Fix registries API usage after rebase
* Remove code I forgot to delete
* Update transmission status display depending on type
* Add testmode_supported
* Update src/pretix/static/pretixbase/js/addressform.js
Co-authored-by: luelista <weller@rami.io>
* Update src/pretix/static/pretixbase/js/addressform.js
Co-authored-by: luelista <weller@rami.io>
* Update src/pretix/static/pretixbase/js/addressform.js
Co-authored-by: luelista <weller@rami.io>
* New mechanism for non-required invoice forms
* Update src/pretix/base/invoicing/transmission.py
Co-authored-by: luelista <weller@rami.io>
* Declare testmode_supported for email
* Make transmission_email_other an implementation detail
* Fix failing tests and add new ones
* Update src/pretix/base/services/invoices.py
Co-authored-by: luelista <weller@rami.io>
* Add emails to email history
* Fix comma error
* More generic default email text
* Cleanup
* Remove "email invoices" button and refine logic
* Rebase migration
* Fix edge case
---------
Co-authored-by: luelista <weller@rami.io>
* Add event date fields, add preliminary range check
* Remove function, use filtered queryset for subevent id limit
* Improve and fix date range check
* Add formfields
* Add tests
* Improve tests
* Add new fields to API and documentation
* Add migration
* Change description according to suggestion
* Change discount apply signature, remove unnecessary query
* Rename new fields, simplify range check
* Rename fields in template
* Apply suggestions from code review
Co-authored-by: Raphael Michel <michel@rami.io>
---------
Co-authored-by: Raphael Michel <michel@rami.io>
Allows organizers to test their shop as if it were a different date and time.
Implemented using a time_machine_now() function which is used instead of regular now(), which can overlay the real date time with a value from a ContextVar, assigned from a session value in EventMiddleware.
For more information, see doc/development/implementation/timemachine.rst
---------
Co-authored-by: Richard Schreiber <schreiber@rami.io>
Co-authored-by: Raphael Michel <michel@rami.io>
This was a bug that took days to find. The story goes like this: A cart
is created with four positions that each include four bundled positions.
A discount is applied, changing the price of *one* of the four top-level
positions to a reduced value. The list of position IDs gets passed to
`perform_order()`, which later passes it on to `transform_cart_positions()`.
`transform_cart_positions()`, however, receives the positions in an order
that has the first-level product *after* the bundled products that
belong to it. Therefore, it can't properly assign the parent-child
relationship between the positions.
The main reason is that cart positions are processed in "database order"
in a number of places, i.e. we make `SELECT` queries without an explicit
`ORDER BY` statement, leading the database to respond in unspecified
order. This is the case for `get_cart()` and hence for `CartMixin.positions`,
and hence for the list of position IDs that is passed to `perform_order()`
and hence for the order in which discounts are processed.
Therefore, if this "databse order" of the cart positions changes, the
discount compuation in `_check_positions()` might make a different choice
of *which* cart position should receive the discount than the CartManager
originally did. That's not nice, but most customers would not even
notice that a different one of their four (otherwise identical) tickets
is now discounted than the cart originally showed.
This leads to `_check_positions()` changing the price on two of the
cart positions. However, it only changes the price on the copy of
the CartPosition object that is directly part of the positions array,
while the `addon_to` attribute of its bundled positions contain a
*different* representation of the same cart position, that is not
refreshed to have the updated price now in the database.
This causes the `CartPosition.sort_key` of the bundled products to be
significantly different from the one of their parent products, which can
cause `transform_cart_positions()` to try to insert them before their
respective parent product, which is how the bug leads to the nasty end
result.
Now, I'm still not sure why this has happened *now* for the first time,
but I suspect it *might* even have something to do with our operations
team tuning our autovacuum parameters on our production installation,
which might make it *more likely* that newly created cart positions are
arbitrarily stored on PostgreSQL disk pages in a different order than
they were inserted than before.
This commit now fixes the bug now in two ways, each of which would be
sufficient to fix it for now, but together they make it hopefully more
stable in the future:
- `perform_order` no longer respects the order of the position IDs it
gets passed in, but instead uses the order last displayed in the cart.
Additionally, both `CartManager` and `_check_positions()` now sort
positions by their `pk` value before applying discounts to ensure
consistent choice of which position is discounted (using `sort_key`
here does not make much sense since it includes sorting by price,
which is about to change).
- `_check_positions()` makes sure that after its completion, only one
copy of the same `CartPosition` is in use that has the current price.
Additionally, this commit makes sure `sort_key` cache is cleared after
e.g. a price change.
It was hard to write a regression test, since "database order" is, by
definition, unreliable, but I tried my best.
* Let plugins allow/prevent the download of individual tickets in an order (#3836)
(extends the functionality of the allow_ticket_download signal)
(cherry picked from commit e20edab98f)
* fix bug where in some cases, only the first ticket could be downloaded