Commit Graph

172 Commits

Author SHA1 Message Date
luelista
5962536a11 Dialog for cart renewal, async task without page refresh (#5148)
* async_task: deduplicate response handling code

* extend cart without full page reload

* update dialog markup

* fix error response from CartExtend

* refactor asynctask, make sure waitingDialog.show() re-initializes dialog contents

* add cart expiry notification

* add aria references to other dialogs

* improve error handling

* fix error if max_extend=None

* different message for expiring soon and expired carts

* refactor dialog css

* add classes to further dialog elements

* switch extend-cart-dialog and loadingmodal to <dialog>

* Backport simple_block_tag from Django 5.2

* Use simple_block_tag for {% dialog %} tag

* add alertdialog role

* Update src/pretix/static/pretixbase/scss/_dialogs.scss

Co-authored-by: Richard Schreiber <schreiber@rami.io>

* fix mobile dialog styles not being overwritten

* asynctask dialog: prevent close by escape on chrome

* remove dynamic aria-live from #cart-deadline

dynamic aria-live is generally not well supported and as we have the dialog now anyways, we can remove it

* move continue-button to right

* Update src/pretix/static/pretixpresale/js/ui/cart.js

Co-authored-by: Richard Schreiber <schreiber@rami.io>

* Fix CSS for old-style dialog

* fix heading display/level

* align dialogs at the top as they originally were

* fix </div> from merge-conflict

* fix missing grow for dialog-content

* improve cart-extend-button ui

* do not show cart-extend-dialog onload

* improve message if 0 minutes

* do not save messae in session if ajax_dont_redirect

* add ajax_dont_redirect to async_task_check_url

* improve draw_deadline to only update #cart-deadline if necessary

* add renew-confirmation-message

---------

Co-authored-by: Richard Schreiber <schreiber@rami.io>
Co-authored-by: Raphael Michel <michel@rami.io>
2025-05-27 07:17:50 +02:00
luelista
a84beef269 [A11y] Cart renewal (#5109)
Allow customers to extend their cart reservation up to 11 times the configured reservation time
2025-05-21 17:02:21 +02:00
Phin Wolkwitz
0b8a7349c7 Discounts: Add applicability date ranges (Z#23151897) (#4927)
* 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>
2025-03-27 15:36:20 +01:00
Mira
fb6117a307 Fix voucher application on "free price" items (Z#23183254) (#4863)
* Do not apply vouchers on "free price" items where more than minimum price is selected

* Do apply vouchers on "free price" items if exactly the minimum price is selected

* Update cart.py

* Add test cases, fix bug in adjacent test

* Fix code style

---------

Co-authored-by: Raphael Michel <michel@rami.io>
2025-02-24 17:14:49 +01:00
Raphael Michel
53f129d5d3 Add codification of tax rates (#4372)
* draft

* .

* Rebase migration

* Update src/pretix/base/models/tax.py

Co-authored-by: Mira <weller@rami.io>

* Test, isort, flake, migration rebase

* carry data & API

* Fix failing tests

* docs fixes

* Improve validation

* Tests

* More fixes

---------

Co-authored-by: Mira <weller@rami.io>
2024-12-13 12:04:38 +01:00
Raphael Michel
6b199a2b9c Allow to enter gift cards into the voucher input (Z#23171961) (#4670) 2024-12-05 13:43:46 +01:00
Raphael Michel
5aba1f9a23 Do not try to delete cart positions twice (PRETIXEU-ARN) 2024-11-07 14:28:35 +01:00
Mira
359df1f51e Cross selling (#4185)
Product categories can now be marked as "cross-selling categories", causing them to 
appear in the add-on checkout step as additional recommendations, depending on 
their cross-selling visibility (always, only if certain products are already in the cart, or 
only if they qualify for a discount according to discount rules).

---------

Co-authored-by: Raphael Michel <michel@rami.io>
Co-authored-by: Richard Schreiber <schreiber@rami.io>
2024-10-14 14:39:49 +02:00
Martin Gross
a77f2d01a7 CartManager: Allow to explicitly set an order expiration 2024-07-19 11:38:36 +02:00
Raphael Michel
4fb5c6bef0 New implementation of sales channels (#4111)
Co-authored-by: Martin Gross <gross@rami.io>
2024-06-30 19:24:30 +02:00
Mira
b638c00952 Time machine mode [Z#23129725] (#3961)
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>
2024-05-17 10:52:17 +02:00
Raphael Michel
0067c3537d Fix invalid orders being created in a complex situation (#4054)
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.
2024-04-08 16:55:54 +02:00
Mira
304d290f22 Presale: improve clientside handling of max-count for add-on products
* Fix typo in error message

* Use exclusive checkboxes for addon items with max_count == 1 and !multi_allowed

* combine exclusive items + variations

* move exclusive to containing fieldset

* fix add-on-exclusive

* add max_count check

* fix plus/minus-stepper buttons bubbling

* Update src/pretix/static/pretixpresale/js/ui/main.js

---------

Co-authored-by: Richard Schreiber <schreiber@rami.io>
2024-03-14 09:17:42 +01:00
Raphael Michel
0ca33eddb1 Cart: More useful error message if some selected products are sold (#3848)
* Cart: More useful error message if some selected products are sold

* Update src/pretix/base/services/cart.py

Co-authored-by: Mira <weller@rami.io>

---------

Co-authored-by: Mira <weller@rami.io>
2024-01-31 14:23:07 +01:00
Raphael Michel
4cd2381a5e Fix CartManager.apply_voucher to handle all_bundles_included 2024-01-22 17:55:32 +01:00
Raphael Michel
4fb49820af Add upper limit on positions in an order (#3806)
* Add upper limit on positions in an order

* Fix form validation
2024-01-19 18:14:45 +01:00
Raphael Michel
c842ea597c New locking mechanism (#2408)
Co-authored-by: Richard Schreiber <schreiber@rami.io>
2023-09-11 11:44:50 +02:00
Raphael Michel
10a83935d9 CartManager: Fix TransactionManagementError
Bug occured when extending a product and deleting it at the same time
2023-08-22 13:42:56 +02:00
Raphael Michel
898d1ab6ed Fix missing pluralization of error message 2023-07-21 14:18:56 +02:00
Raphael Michel
59a16789ea CartManager: Fix crash PRETIXEU-8NF 2023-06-26 11:12:13 +02:00
Raphael Michel
c75c080c5c Vouchers: Allow to set all addons or bundles as included (#3322)
Co-authored-by: Richard Schreiber <schreiber@rami.io>
2023-05-22 11:59:27 +02:00
Raphael Michel
d0b449ea89 Reusable media (#3131)
Co-authored-by: Martin Gross <gross@rami.io>
2023-04-03 10:45:22 +02:00
Richard Schreiber
e9b22b7d33 Cart: ensure free price input is decimal (PRETIXEU-80N)
Co-authored-by: Phin Wolkwitz <wolkwitz@rami.io>
2023-03-21 08:51:49 +01:00
Raphael Michel
369251b0b0 Fix confusion between tax rate and tax value 2023-03-16 22:47:23 +01:00
Raphael Michel
e83798a9b7 Increase validated size of prices 2023-03-16 21:33:06 +01:00
Raphael Michel
c5b7ff66b7 Fix incorrecly used error messages 2023-01-31 22:11:53 +01:00
Richard Schreiber
a7f9e100d2 Clean up localization or error messages in cart (#3049) 2023-01-30 17:24:09 +01:00
Richard Schreiber
a1ec45daf6 Fix addon typo (#2987) 2022-12-20 09:15:38 +01:00
Raphael Michel
9624b1c505 Support for external gift cards (#2912) 2022-11-23 14:52:56 +01:00
Raphael Michel
f923c2fed0 Fix price calculation of included add-ons in expired carts 2022-11-18 17:24:02 +01:00
Raphael Michel
e32e7e2a50 Add clever handling of plus button in cart with voucher (#2893) 2022-11-14 16:55:39 +01:00
Raphael Michel
3fe2a0455f Fix crash in CartManager 2022-11-01 12:14:30 +01:00
Raphael Michel
45f579caf2 Vouchers: Fix label on redemption page 2022-10-25 15:00:00 +02:00
Raphael Michel
d69d70cfb1 Voucher: Add min_usages parameter (#2853) 2022-10-20 18:07:24 +02:00
Raphael Michel
9da68645da Replace phrase "presale period" with "booking period" 2022-10-11 11:34:23 +02:00
Raphael Michel
38969747f4 API: New implementation for cart creation (#2833) 2022-10-10 12:59:38 +02:00
Raphael Michel
d628acc62a Remove left-over debug statements 2022-07-21 09:14:38 +02:00
Raphael Michel
23e5af13ad Fix untranslated error message 2022-07-12 15:07:34 +02:00
Raphael Michel
ed4bc87198 Show better error message if a gift card is used in apply_voucher 2022-05-11 17:06:20 +02:00
Raphael Michel
6fee0ac0a9 Discounts (#2510) 2022-04-27 14:43:16 +02:00
Raphael Michel
6f0da5c2ca TaxRules: Add internal_name and keep_gross_if_rate_changes (#2422)
Co-authored-by: ser8phin <eva.wolkwitz@gmx.de>
2022-01-21 15:39:27 +01:00
Raphael Michel
17adde99fa Allow to restrict availability of variations by date, sales channel, and voucher (#2202) 2021-09-15 12:04:17 +02:00
Raphael Michel
35c6975270 Cart Manager: Fix counting of bundled items 2021-05-18 12:14:22 +02:00
Raphael Michel
4acf660906 Fix #1567 -- Per-subevent availability of items (#2040) 2021-04-29 15:34:58 +02:00
Raphael Michel
a93287207b pretix Community Edition moves to AGPLv3-based license (#2023) 2021-04-12 10:33:47 +02:00
Raphael Michel
8101a9d8ae CartManager: Fix a cache handling bug 2021-03-31 10:37:49 +02:00
Aksh Gupta
88ba7ab53a Refactor code quality issues (#2001) 2021-03-16 19:13:02 +01:00
Raphael Michel
6d9e1be844 Tax rules: Allow to block countries from making a purchase 2020-11-22 13:46:15 +01:00
Raphael Michel
f6dc90fb28 Show message and cart after tax rate has changed 2020-10-30 22:33:44 +01:00
Raphael Michel
f54bf3f1ea Specific error message for payment_ended 2020-10-08 09:28:53 +02:00