pretix-event-analytics 2.2.1__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.
- pretix_event_analytics-2.2.1/CHANGELOG.md +392 -0
- pretix_event_analytics-2.2.1/LICENSE +191 -0
- pretix_event_analytics-2.2.1/MANIFEST.in +8 -0
- pretix_event_analytics-2.2.1/PKG-INFO +354 -0
- pretix_event_analytics-2.2.1/README.md +326 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/__init__.py +24 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/_compat.py +32 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/_safety.py +53 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/admin.py +77 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/apps.py +17 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/exporters.py +353 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/forms.py +381 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/locale/README.md +19 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/management/__init__.py +0 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/management/commands/__init__.py +0 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/management/commands/analytics_resync.py +176 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/management/commands/generate_test_data.py +518 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/migrations/0001_initial.py +238 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/migrations/0002_analyticsidentity_and_more.py +135 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/migrations/0003_audit_fixes.py +60 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/migrations/0004_performance_and_integrity.py +42 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/migrations/0005_suite_v2.py +233 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/migrations/0006_people_resolved_at.py +18 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/migrations/0007_sales_annotations.py +30 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/migrations/0008_pace_alerts.py +28 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/migrations/0009_accuracy_2_1.py +93 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/migrations/0010_nationality_bank_country.py +38 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/migrations/__init__.py +0 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/models.py +520 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/__init__.py +0 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/age_bucketer.py +140 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/alerts.py +114 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/attendance.py +118 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/cohort_service.py +61 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/country_resolver.py +261 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/hash_service.py +136 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/id_country.py +180 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/identity_keys.py +72 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/ingest.py +172 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/legacy.py +138 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/normalizer.py +425 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/payment_info.py +122 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/people.py +722 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/predictor.py +84 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/repeat_detector.py +121 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/reports/__init__.py +0 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/reports/audience.py +253 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/reports/charts.py +70 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/reports/loyalty.py +323 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/reports/market.py +53 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/reports/operations.py +170 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/reports/overview.py +112 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/reports/sales.py +491 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/reports/scope.py +232 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/reports/series.py +62 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/reports/tickets.py +143 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/resale.py +295 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/resync_service.py +173 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/van_length_bucketer.py +120 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/services/versioning.py +66 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/shredder.py +79 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/signals.py +277 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/static/pretix_event_analytics/chart.umd.min.js +19 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/static/pretix_event_analytics/dashboard.css +273 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/static/pretix_event_analytics/dashboard.js +368 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/tasks.py +225 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/templates/pretix_event_analytics/_chart.html +27 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/templates/pretix_event_analytics/base.html +132 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/templates/pretix_event_analytics/config.html +184 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/templates/pretix_event_analytics/email/pace_alert.txt +7 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/templates/pretix_event_analytics/pages/audience.html +119 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/templates/pretix_event_analytics/pages/loyalty.html +225 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/templates/pretix_event_analytics/pages/operations.html +89 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/templates/pretix_event_analytics/pages/overview.html +93 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/templates/pretix_event_analytics/pages/resale.html +75 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/templates/pretix_event_analytics/pages/sales.html +203 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/templates/pretix_event_analytics/pages/tickets.html +110 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/templates/pretix_event_analytics/pdf_report.html +132 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/templates/pretix_event_analytics/series_confirm_delete.html +38 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/templates/pretix_event_analytics/series_detail.html +116 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/templates/pretix_event_analytics/series_form.html +65 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/templates/pretix_event_analytics/series_list.html +84 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/templatetags/__init__.py +0 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/templatetags/analytics_tags.py +39 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/urls.py +38 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics/views.py +600 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics.egg-info/PKG-INFO +354 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics.egg-info/SOURCES.txt +108 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics.egg-info/dependency_links.txt +1 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics.egg-info/entry_points.txt +2 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics.egg-info/not-zip-safe +1 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics.egg-info/requires.txt +2 -0
- pretix_event_analytics-2.2.1/pretix_event_analytics.egg-info/top_level.txt +1 -0
- pretix_event_analytics-2.2.1/setup.cfg +55 -0
- pretix_event_analytics-2.2.1/setup.py +2 -0
- pretix_event_analytics-2.2.1/tests/test_alerts.py +78 -0
- pretix_event_analytics-2.2.1/tests/test_correctness.py +140 -0
- pretix_event_analytics-2.2.1/tests/test_country.py +295 -0
- pretix_event_analytics-2.2.1/tests/test_csp.py +52 -0
- pretix_event_analytics-2.2.1/tests/test_features.py +156 -0
- pretix_event_analytics-2.2.1/tests/test_matching.py +153 -0
- pretix_event_analytics-2.2.1/tests/test_migrations.py +34 -0
- pretix_event_analytics-2.2.1/tests/test_packaging.py +50 -0
- pretix_event_analytics-2.2.1/tests/test_payment_info.py +51 -0
- pretix_event_analytics-2.2.1/tests/test_people.py +159 -0
- pretix_event_analytics-2.2.1/tests/test_reports.py +104 -0
- pretix_event_analytics-2.2.1/tests/test_resale.py +142 -0
- pretix_event_analytics-2.2.1/tests/test_smoke.py +57 -0
- pretix_event_analytics-2.2.1/tests/test_views.py +272 -0
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All user-visible changes to this project are documented here. Dates are in
|
|
4
|
+
ISO 8601. The project follows [Semantic Versioning](https://semver.org/).
|
|
5
|
+
|
|
6
|
+
## [2.2.1] — 2026-10-02
|
|
7
|
+
|
|
8
|
+
No migration, no resync needed.
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- The sales-pace chart (Overview, Sales) marks only this edition's and the previous edition's moments;
|
|
12
|
+
with every edition's it became a fence of lines. Each edition's own moments stay on its Sales page.
|
|
13
|
+
- Examples and placeholders are generic ("My Festival") instead of one organiser's event.
|
|
14
|
+
- Requires `pretix>=2026.2` in the package metadata (it already refused older versions at runtime).
|
|
15
|
+
- README: screenshots, a *Theming* section documenting the `--pa-*` CSS variables as public API,
|
|
16
|
+
current badges and import description.
|
|
17
|
+
- Deployment notes for a specific installation moved out of this repository.
|
|
18
|
+
|
|
19
|
+
## [2.2.0] — 2026-09-26
|
|
20
|
+
|
|
21
|
+
**Run a resync of every edition after upgrading** (data version 4). One database
|
|
22
|
+
migration (0010, fields added only, reversible).
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
- **Nationality, kept apart from residence.** Per ticket holder, from a
|
|
26
|
+
nationality question (country names *and* demonyms such as "Portuguese") or
|
|
27
|
+
from an ID document that proves citizenship. New "Nationality" panel on the
|
|
28
|
+
Audience page (replaces "ID-document country"), and `nationality` columns in
|
|
29
|
+
the order and ticket CSV exports.
|
|
30
|
+
- ID-document rules now declare what they prove (`id_country.PROVES`): citizens'
|
|
31
|
+
IDs (Spanish DNI, Portuguese Cartão de Cidadão / civil number, Italian codice
|
|
32
|
+
fiscale of someone born in Italy) prove **nationality**; the Spanish NIE (issued
|
|
33
|
+
to foreigners), UK driving licence and Belgian national number / eID prove
|
|
34
|
+
**residence**.
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
- **Exact residence = what the buyer stated** (residence question, invoice,
|
|
38
|
+
PayPal, card billing address) or a residence document. The paying bank's
|
|
39
|
+
country (card issuer, IBAN) and the buyer's nationality are now **probable**
|
|
40
|
+
residence only. Measured on SUTI 2026, the card issuer agreed with the ID
|
|
41
|
+
document 79% and the invoice address 86% of the time, and foreign-issued
|
|
42
|
+
cards (Israel, UK, …) mostly belonged to people with Portuguese documents.
|
|
43
|
+
- Derived-country order: same customer's other orders (inferred) → buyer's
|
|
44
|
+
nationality → card issuer → IBAN → e-mail domain (all probable).
|
|
45
|
+
- "Same customer's other orders" only uses exact countries as evidence, so a
|
|
46
|
+
bank's country never spreads to other orders.
|
|
47
|
+
- "Local buyer" now needs an exact residence country.
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
- Placeholder ID numbers made of one repeated digit ("00000000") no longer
|
|
51
|
+
resolve to a country.
|
|
52
|
+
|
|
53
|
+
## [2.1.1] — 2026-09-25
|
|
54
|
+
|
|
55
|
+
### Fixed
|
|
56
|
+
- **Resale showed 0 TicketSwap resales** with TicketSwap 1.x, which keeps
|
|
57
|
+
swaps in its own table (`TicketSwapSwap`, successful rows) instead of on
|
|
58
|
+
the ticket. Both record shapes are now read (1.x table, 2.x ticket
|
|
59
|
+
counters), read-only — only positions, dates and the success flag, never
|
|
60
|
+
the stored names or e-mails.
|
|
61
|
+
- TicketSwap swap dates (1.x) now appear on the monthly chart, stacked with
|
|
62
|
+
manual name changes.
|
|
63
|
+
- Resale counts **admission tickets only** in both channels and in the
|
|
64
|
+
total, so add-ons and stand-alone extras (parking, camper passes) no longer
|
|
65
|
+
skew the rate.
|
|
66
|
+
|
|
67
|
+
No migration. No resync needed (Resale reads Pretix data live).
|
|
68
|
+
|
|
69
|
+
## [2.1.0] — 2026-09-25
|
|
70
|
+
|
|
71
|
+
**Run a resync of every edition after upgrading** — returning-people figures
|
|
72
|
+
change meaning (see below). One database migration (fields added, one
|
|
73
|
+
constraint widened).
|
|
74
|
+
|
|
75
|
+
### Changed
|
|
76
|
+
- **Returning people are matched on name + birth date only.** A person is a
|
|
77
|
+
ticket holder. Sharing a card, a PayPal account or an e-mail no longer makes
|
|
78
|
+
two ticket holders the same person (people buy for friends). Names are
|
|
79
|
+
compared ignoring accents, case, word order, middle names and added second
|
|
80
|
+
surnames; different birth dates never match.
|
|
81
|
+
- **When in doubt, unknown.** Tickets without a usable name + birth date,
|
|
82
|
+
ambiguous names and placeholder data (the same identity on 3+ tickets of one
|
|
83
|
+
edition) are left out of returning-people figures instead of being guessed.
|
|
84
|
+
A conservative *probable* tier (no birth date, one matching person, shared
|
|
85
|
+
e-mail or card) is shown only as "including probable matches".
|
|
86
|
+
- **Customers** (returning buyers) are matched on the order e-mail only;
|
|
87
|
+
payment fingerprints are no longer used to link buyers.
|
|
88
|
+
- **Country of residence** comes from the first available source, stored with
|
|
89
|
+
it: residence question → invoice address → PayPal address/account → card
|
|
90
|
+
billing address → ID-document country (opt-in) → IBAN → card's issuing
|
|
91
|
+
bank. Invoice addresses now beat card countries. Exact country names only
|
|
92
|
+
(no fuzzy matching).
|
|
93
|
+
- **Resale** shows one "changed hands" total: TicketSwap resales (read-only,
|
|
94
|
+
from the TicketSwap plugin's ticket data) plus manual name changes, counted
|
|
95
|
+
once per ticket, with a channel breakdown, by product, current holders and a
|
|
96
|
+
CSV of order codes. A manual name change counts only with evidence (birth
|
|
97
|
+
date or attendee e-mail changed too, or a clearly different second rename);
|
|
98
|
+
other single edits are reported as "unclear".
|
|
99
|
+
|
|
100
|
+
### Added
|
|
101
|
+
- **Derived countries, kept apart from exact ones.** For orders with no exact
|
|
102
|
+
source: *inferred* — the same customer's country on their other orders
|
|
103
|
+
(same order e-mail, or the buyer holding a ticket as the same person),
|
|
104
|
+
only when all of them agree; *probable* — the e-mail's country domain
|
|
105
|
+
(.pt, .es, .uk …; generic and vanity domains ignored). Stored in separate
|
|
106
|
+
fields, never in the country used by filters and other pages. Audience has
|
|
107
|
+
an **Exact / + inferred / + probable** switch; orders CSV has the columns.
|
|
108
|
+
- PayPal v2 order data: country from `payer.address` and
|
|
109
|
+
`payment_source.paypal.address` (pretix 2025+ stores v2).
|
|
110
|
+
- "Travelling from" question support and a breakdown on the Audience page,
|
|
111
|
+
plus "How the country is known" coverage by source.
|
|
112
|
+
- Opt-in ID-document country (settings → "Where people come from"): issuing
|
|
113
|
+
country from national ID formats with a valid check digit; the number is
|
|
114
|
+
never stored.
|
|
115
|
+
- Past-edition imports accept a CSV with name + birth-date columns.
|
|
116
|
+
- Tickets CSV: match tier, returning incl. probable, document country.
|
|
117
|
+
|
|
118
|
+
### Fixed
|
|
119
|
+
- Dashboard widgets showed raw HTML on Pretix 2026.7 (content is now marked safe).
|
|
120
|
+
- Two tickets of one order carrying the same signal (e.g. the same attendee
|
|
121
|
+
e-mail) kept it only on the first ticket.
|
|
122
|
+
- Win-back list and loyalty CSV mixed customer and person keys.
|
|
123
|
+
|
|
124
|
+
## [2.0.3] — 2026-09-25
|
|
125
|
+
|
|
126
|
+
### Fixed
|
|
127
|
+
- Stripe card details were read from the wrong place. Pretix stores Stripe
|
|
128
|
+
payments as PaymentIntents (card under `charges.data[].payment_method_details`),
|
|
129
|
+
so card country and card fingerprint were never found: buyers without an
|
|
130
|
+
invoice address showed as "Unknown" country, and returning buyers who
|
|
131
|
+
changed e-mail but paid with the same card were not recognised. Now reads
|
|
132
|
+
PaymentIntent, `latest_charge`, Charge and legacy card-source shapes; also
|
|
133
|
+
accepts the `stripe_cc` / `paypal2` provider identifiers.
|
|
134
|
+
**Run a resync after upgrading** so existing orders pick this up.
|
|
135
|
+
|
|
136
|
+
## [2.0.2] — 2026-09-25
|
|
137
|
+
|
|
138
|
+
### Changed
|
|
139
|
+
- New `--pa-accent` variable for UI states (active tab, selected segment,
|
|
140
|
+
quick-range pill, callout border, toggles, attendance dots). It defaults to
|
|
141
|
+
the first chart colour, so nothing changes visually, but a theme can now
|
|
142
|
+
give the UI its brand accent without recolouring the chart series.
|
|
143
|
+
|
|
144
|
+
## [2.0.1] — 2026-09-25
|
|
145
|
+
|
|
146
|
+
### Fixed
|
|
147
|
+
- Themed (e.g. dark) control panels: every colour is now a CSS variable and
|
|
148
|
+
every surface sets its own text colour, while text placed directly on the
|
|
149
|
+
page follows the host theme. Previously the settings page used fixed white
|
|
150
|
+
cards, so headings and labels became invisible under a dark theme with
|
|
151
|
+
light text, and some dashboard text was drawn dark on a dark page.
|
|
152
|
+
- The settings and series pages share the dashboard's variable scope, so a
|
|
153
|
+
theme that remaps `--pa-*` variables styles them too.
|
|
154
|
+
- Chart tooltips take their colours from variables.
|
|
155
|
+
|
|
156
|
+
### Changed
|
|
157
|
+
- Plugin author shown in Pretix is now "Hexadexa".
|
|
158
|
+
|
|
159
|
+
## [2.0.0] — 2026-09-25
|
|
160
|
+
|
|
161
|
+
A rebuild into a full analytics suite. **Upgrade steps:** update the
|
|
162
|
+
package, run `python -m pretix migrate`, `python -m pretix rebuild`, set the
|
|
163
|
+
salt in `pretix.cfg` if you used a Django setting that Pretix never
|
|
164
|
+
loaded, then run `python -m pretix analytics_resync --all`. Until the
|
|
165
|
+
resync runs, the dashboard shows a notice for rows produced by 1.x.
|
|
166
|
+
|
|
167
|
+
### New — dashboard suite
|
|
168
|
+
- Seven pages sharing one filter bar: Overview, Sales, Audience, Loyalty,
|
|
169
|
+
Tickets, Operations, Resale; sidebar sub-navigation.
|
|
170
|
+
- **Sales:** tickets and revenue over time as aligned charts (day / week /
|
|
171
|
+
month, cumulative toggle), split by product, category, new vs returning
|
|
172
|
+
or country, by order or payment date; price-tier markers; editions
|
|
173
|
+
compared on a days-before-event axis; same-point comparison table;
|
|
174
|
+
forecast with range; ticket and revenue targets; weekday × hour heatmap;
|
|
175
|
+
purchase-timing buckets.
|
|
176
|
+
- **Loyalty:** first-timer share, times attended before, came back after a
|
|
177
|
+
gap, lost since the last edition, at every edition; choose any editions
|
|
178
|
+
to compare — attended once/twice/…, overlap matrix, attendance patterns,
|
|
179
|
+
edition flow, first-timer cohorts; people or buyers-only; first-timer
|
|
180
|
+
segments by product, country, age and purchase timing.
|
|
181
|
+
- **Audience, Tickets, Operations:** product performance, categories,
|
|
182
|
+
variations, price tiers, add-ons, vouchers, check-in and arrivals,
|
|
183
|
+
no-shows, cancellations over time, opt-in question breakdowns.
|
|
184
|
+
- **Series overview** page and **past attendee-list import** (hashed).
|
|
185
|
+
- **Like-for-like KPIs** against the previous edition at the same point
|
|
186
|
+
in its sales cycle.
|
|
187
|
+
- **Exports:** tickets CSV, "returning buyers by order code" CSV, full PDF
|
|
188
|
+
report, and exporters in Pretix's own Export menu (CSV/Excel).
|
|
189
|
+
|
|
190
|
+
### Fixed — correctness
|
|
191
|
+
- Orders with several tickets of the same product lost tickets during live
|
|
192
|
+
ingestion and were skipped entirely by resync.
|
|
193
|
+
- Returning status depended on the order in which editions were synced;
|
|
194
|
+
it is now resolved series-wide after every change.
|
|
195
|
+
- Attendee e-mails were hashed but never used; a friend's ticket in one
|
|
196
|
+
year and an own purchase later now match. Group orders no longer merge
|
|
197
|
+
their attendees into one person.
|
|
198
|
+
- The cohort matrix used a different definition of "returning" than the
|
|
199
|
+
KPIs; both now use the same resolved people.
|
|
200
|
+
- A check-in removed the early-purchase points from the return score.
|
|
201
|
+
- With several events selected, ticket, add-on and refund figures still
|
|
202
|
+
showed only the current event.
|
|
203
|
+
- Resync emptied the table first (blank dashboard during a resync, partial
|
|
204
|
+
data after a failure) and dropped canceled/refunded orders, so the
|
|
205
|
+
refund rate read 0 after any resync.
|
|
206
|
+
- Daily/hourly charts used UTC instead of the event's timezone; the hourly
|
|
207
|
+
chart also shifted by the viewer's browser timezone.
|
|
208
|
+
- Ages were computed on the day of the sync instead of the event date.
|
|
209
|
+
- Persona "add-on rate" actually showed the caravan rate.
|
|
210
|
+
- Net revenue and tax ignored fees.
|
|
211
|
+
- Series pages crashed on Pretix 2026 (non-existent base template).
|
|
212
|
+
- Cohort tooltips showed "0 of buyers".
|
|
213
|
+
- The salt could only be set as a Django setting, which Pretix installs do
|
|
214
|
+
not load; `pretix.cfg` and environment variables now work.
|
|
215
|
+
|
|
216
|
+
### New — also in 2.0.0
|
|
217
|
+
- **Win-back lists:** people from the previous edition who have not
|
|
218
|
+
bought yet, and people who came earlier but skipped the last edition —
|
|
219
|
+
exported as the order code of their most recent visit.
|
|
220
|
+
- **Moments:** dated notes ("line-up announced") drawn on the sales charts
|
|
221
|
+
and on the edition comparison, next to automatic price-tier markers.
|
|
222
|
+
- **Capacity** per quota (paid, pending, available, waiting list), live
|
|
223
|
+
from Pretix.
|
|
224
|
+
- **Payment completion** by method: paid vs pending vs expired unpaid.
|
|
225
|
+
- **Top cities** in the Audience page.
|
|
226
|
+
- **Quick date ranges** (7 / 30 / 90 days, all time) in the filter bar.
|
|
227
|
+
- **Pretix dashboard widgets:** returning buyers and first-time attendees
|
|
228
|
+
on the event's main dashboard.
|
|
229
|
+
- **Pace alerts:** e-mail chosen addresses when ticket sales trail the
|
|
230
|
+
previous edition (same number of days before the event) by a chosen
|
|
231
|
+
percentage; at most once a week while behind. Runs from Pretix's cron.
|
|
232
|
+
- **Calmer settings and filters:** the settings page is grouped into
|
|
233
|
+
*This edition* (required) and collapsible *Goals & alerts*, *Question
|
|
234
|
+
insights* and *Advanced* sections, each with a one-line summary; the
|
|
235
|
+
dashboard filter bar keeps the common filters visible and folds the rest
|
|
236
|
+
under *More filters* (opens automatically when one is in use); long pages
|
|
237
|
+
get an "On this page" jump bar.
|
|
238
|
+
|
|
239
|
+
### Security
|
|
240
|
+
- The "merge editions" filter and all series-wide figures (Loyalty,
|
|
241
|
+
first-timer headline, edition comparisons, resale by edition, series
|
|
242
|
+
overview) respect per-event team permissions: a member limited to one
|
|
243
|
+
event can no longer read other editions' data.
|
|
244
|
+
- CSV exports neutralise spreadsheet formulas in buyer-supplied fields.
|
|
245
|
+
|
|
246
|
+
### Compatibility
|
|
247
|
+
- Tested on Pretix 2026.2.0 and 2026.3.1. Uses the new permission names
|
|
248
|
+
(`event.orders:read`, …) on 2026.3+ and the legacy ones before.
|
|
249
|
+
- Declared as an event + organizer plugin: **enable it in the organizer's
|
|
250
|
+
plugin settings as well as per event.**
|
|
251
|
+
- All markup is compatible with Pretix's Content-Security-Policy
|
|
252
|
+
(`style-src 'self'`): no inline style attributes; 1.x's inline styles
|
|
253
|
+
were silently ignored by browsers.
|
|
254
|
+
|
|
255
|
+
### Changed
|
|
256
|
+
- Resync upserts instead of delete-and-rebuild, always includes check-ins,
|
|
257
|
+
keeps its lock alive per chunk, and resolves returning people once per
|
|
258
|
+
series. Live orders wait for a running resync instead of being dropped.
|
|
259
|
+
- Returning-people resolution runs as one debounced background task per
|
|
260
|
+
series (with a Celery worker) or from Pretix's periodic cron task
|
|
261
|
+
(without one) — never inside a buyer's payment request. Admin actions
|
|
262
|
+
queue it instead of blocking the page.
|
|
263
|
+
- Payment fingerprints shared by more than four orders in one edition
|
|
264
|
+
(agency, company account, box office) no longer link people together.
|
|
265
|
+
- Order changes, attendee edits, reactivations and splits are re-ingested.
|
|
266
|
+
- Report results are cached per organizer data version and plugin version.
|
|
267
|
+
- Charts: validated colour-blind-safe palette, no dual axes, table view.
|
|
268
|
+
|
|
269
|
+
### Development
|
|
270
|
+
- pytest suite (~80 tests) against real Pretix objects.
|
|
271
|
+
- `scripts/dev_seed_orders.py` seeds real orders into a local dev DB.
|
|
272
|
+
|
|
273
|
+
## [1.2.0] — 2026-04-24
|
|
274
|
+
|
|
275
|
+
A correctness, safety, and polish release. No breaking schema changes;
|
|
276
|
+
existing installations upgrade by updating the package and running
|
|
277
|
+
`python -m pretix migrate` (no-op if migrations are already applied).
|
|
278
|
+
|
|
279
|
+
### Safety — read-only against the Pretix ticketing database
|
|
280
|
+
|
|
281
|
+
- Added `scripts/check_isolation.py`, a standalone static check that
|
|
282
|
+
greps the plugin source for any call that would write, update, or
|
|
283
|
+
delete a Pretix core table (Order, OrderPosition, OrderPayment,
|
|
284
|
+
LogEntry, Event, Item, Question, Checkin, …). Runs with no database,
|
|
285
|
+
suitable for CI.
|
|
286
|
+
- Added `pretix_event_analytics/_safety.py` as the single source of
|
|
287
|
+
truth for the read-only contract.
|
|
288
|
+
- Removed the synthetic `LogEntry` rows that `generate_test_data`
|
|
289
|
+
previously inserted into the Pretix audit log for secondary-market
|
|
290
|
+
testing. The plugin now writes to its own tables only.
|
|
291
|
+
- `generate_test_data` now refuses to run with `DEBUG=False` unless
|
|
292
|
+
`--i-understand-this-is-fake-data` is passed. `--clear` prompts for
|
|
293
|
+
explicit confirmation when real analytics rows would be deleted.
|
|
294
|
+
|
|
295
|
+
### Correctness
|
|
296
|
+
|
|
297
|
+
- `PRETIX_ANALYTICS_SECRET_SALT` is now required in production and
|
|
298
|
+
validated to be at least 16 characters. Missing / too-short salt
|
|
299
|
+
raises `ImproperlyConfigured` on first use. In `DEBUG=True`
|
|
300
|
+
environments, a `SECRET_KEY`-derived fallback is used with a clear
|
|
301
|
+
one-time log warning.
|
|
302
|
+
- `generate_repeat_hash("")` now returns an empty string. Previously,
|
|
303
|
+
every order without an email collided on the HMAC of the empty
|
|
304
|
+
string and was wrongly flagged as a repeat buyer of every other
|
|
305
|
+
email-less order.
|
|
306
|
+
- Resync and live ingestion no longer race. A shared cache lock is
|
|
307
|
+
published while a resync is rebuilding facts; `order_paid`,
|
|
308
|
+
`order_canceled`, and `checkin_created` Celery tasks detect the
|
|
309
|
+
lock and requeue themselves until the rebuild finishes.
|
|
310
|
+
- Per-order repeat detection is now wrapped in `transaction.atomic()`
|
|
311
|
+
inside the resync path, matching the live-ingestion path.
|
|
312
|
+
- `process_order_paid` distinguishes expected `ValueError` (bad data,
|
|
313
|
+
skip) from unexpected exceptions (bug, retry with backoff) so that
|
|
314
|
+
a single upstream schema surprise no longer silently drops every
|
|
315
|
+
paid order.
|
|
316
|
+
- `process_checkin_created` now requeues with backoff when the
|
|
317
|
+
corresponding `AnalyticsOrderFact` is not yet created, instead of
|
|
318
|
+
silently dropping the check-in.
|
|
319
|
+
- Unicode normalization (NFKC) applied before hashing so that
|
|
320
|
+
visually-identical emails with different Unicode representations
|
|
321
|
+
hash identically.
|
|
322
|
+
- Van-length buckets (`<6m`, `6–8m`, `>8m`) have documented inclusive
|
|
323
|
+
/ exclusive boundaries and reject negative input lengths.
|
|
324
|
+
- Normalizer rejects orders with zero positions (previously stored a
|
|
325
|
+
degenerate fact row with `ticket_count=0`).
|
|
326
|
+
|
|
327
|
+
### Security
|
|
328
|
+
|
|
329
|
+
- Export filenames are now strictly `[A-Za-z0-9_-]+`, truncated to 50
|
|
330
|
+
chars; null bytes, path separators, and traversal sequences are
|
|
331
|
+
dropped.
|
|
332
|
+
- `TriggerResyncView` adds a per-user 60-second throttle in addition
|
|
333
|
+
to the existing per-event in-progress lock, so a refresh-loop or
|
|
334
|
+
scripted client can no longer flood the Celery queue.
|
|
335
|
+
- `DashboardFilterForm.editions` is now scoped to the current event's
|
|
336
|
+
organizer on both `choices` population and `clean()`, so posting
|
|
337
|
+
event ids from another organizer has no effect.
|
|
338
|
+
|
|
339
|
+
### Performance
|
|
340
|
+
|
|
341
|
+
- Dashboard refund stats folded into a single aggregate query (was
|
|
342
|
+
two `.count()` calls against the same unfiltered queryset).
|
|
343
|
+
- Add-on attach-rate segmentation rewritten: previously one subquery
|
|
344
|
+
per age bucket (N+1 against `AnalyticsTicketFact`); now a single
|
|
345
|
+
`values("age_range").annotate(...)` with pre-computed add-on set
|
|
346
|
+
membership. Payload reduces from 1 + 2 + 6 queries down to 3.
|
|
347
|
+
|
|
348
|
+
### UI / UX
|
|
349
|
+
|
|
350
|
+
- Cohort retention heatmap has a visible colour legend and
|
|
351
|
+
distinguishes "no data" cells from "source year is later" cells.
|
|
352
|
+
- Dashboard shows active-filter chips below the filter bar so the
|
|
353
|
+
currently applied filters are always visible.
|
|
354
|
+
- Date range filter (`From` / `To`) now validates that the start is
|
|
355
|
+
on or before the end.
|
|
356
|
+
- PDF export is fully `{% trans %}`-wrapped and now includes the
|
|
357
|
+
event date in the header, a cohort colour legend, and pluralised
|
|
358
|
+
buyer counts.
|
|
359
|
+
- `pretix_event_analytics/locale/` skeleton directory added so
|
|
360
|
+
translators can be on-boarded via `makemessages` / Transifex /
|
|
361
|
+
Crowdin.
|
|
362
|
+
|
|
363
|
+
### Internal
|
|
364
|
+
|
|
365
|
+
- Age-confirmation keyword list consolidated in `age_bucketer.py`
|
|
366
|
+
(was duplicated between `age_bucketer.py` and `normalizer.py`).
|
|
367
|
+
- Module docstrings in `tasks.py` and `resync_service.py` now state
|
|
368
|
+
the read-only invariant explicitly.
|
|
369
|
+
|
|
370
|
+
## [1.1.1] — 2026-04-08
|
|
371
|
+
|
|
372
|
+
- Consolidated dashboard count queries into a single aggregate
|
|
373
|
+
(6 queries → 1).
|
|
374
|
+
- Added `acks_late` to all Celery tasks to prevent message loss if a
|
|
375
|
+
worker crashes mid-task.
|
|
376
|
+
|
|
377
|
+
## [1.1.0] — 2026-04-08
|
|
378
|
+
|
|
379
|
+
Initial public release.
|
|
380
|
+
|
|
381
|
+
- HMAC-SHA256 identity resolution across email, Stripe card
|
|
382
|
+
fingerprints, PayPal payer IDs, bank IBANs, and name + DOB
|
|
383
|
+
composites.
|
|
384
|
+
- Forward-looking cohort retention heatmap.
|
|
385
|
+
- Deterministic repeat-probability scoring (0–100), refined
|
|
386
|
+
post-event via check-in data.
|
|
387
|
+
- Revenue KPIs, geographic and demographic breakdowns, sales pacing
|
|
388
|
+
chart, buyer-persona segmentation, add-on attach rates, caravan
|
|
389
|
+
analysis, and secondary-market (resale) detection.
|
|
390
|
+
- Multi-edition filtering, CSV and PDF export.
|
|
391
|
+
- GDPR data shredder integrated with Pretix's deletion workflow.
|
|
392
|
+
- Asynchronous Celery ingestion with retry + exponential backoff.
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to the Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by the Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding any notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
Copyright 2024-2026 Andre Vidal
|
|
180
|
+
|
|
181
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
182
|
+
you may not use this file except in compliance with the License.
|
|
183
|
+
You may obtain a copy of the License at
|
|
184
|
+
|
|
185
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
186
|
+
|
|
187
|
+
Unless required by applicable law or agreed to in writing, software
|
|
188
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
189
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
190
|
+
See the License for the specific language governing permissions and
|
|
191
|
+
limitations under the License.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
include LICENSE
|
|
2
|
+
include README.md
|
|
3
|
+
recursive-include pretix_event_analytics/templates *
|
|
4
|
+
recursive-include pretix_event_analytics/static *
|
|
5
|
+
recursive-include pretix_event_analytics/locale *
|
|
6
|
+
include pretix_event_analytics/migrations/*.py
|
|
7
|
+
include CHANGELOG.md
|
|
8
|
+
global-exclude *.map *.pyc .DS_Store
|