]>
git.ipfire.org Git - ipfire.org.git/blob - src/web/donate.py
9 "monthly" : "IPFIRE-DONATION-MONTHLY",
10 "quarterly" : "IPFIRE-DONATION-QUARTERLY",
11 "yearly" : "IPFIRE-DONATION-YEARLY",
13 DEFAULT_SKU
= "IPFIRE-DONATION"
15 class DonateHandler(base
.AnalyticsMixin
, base
.BaseHandler
):
18 country
= self
.current_user
.country_code
20 country
= self
.current_country_code
23 amount
= self
.get_argument_float("amount", None)
24 currency
= self
.get_argument("currency", None)
25 frequency
= self
.get_argument("frequency", None)
27 # Set default currency
28 if not currency
in ("EUR", "USD"):
31 # Default to USD for the US only
35 # Set default frequency
36 if not frequency
in ("one-time", "monthly"):
37 frequency
= "one-time"
39 self
.render("donate/donate.html", countries
=iso3166
.countries
,
40 country
=country
, amount
=amount
, currency
=currency
, frequency
=frequency
)
42 @base.ratelimit(minutes
=15, requests
=5)
44 type = self
.get_argument("type")
45 if not type in ("individual", "organization"):
46 raise tornado
.web
.HTTPError(400, "type is of an invalid value: %s" % type)
48 amount
= self
.get_argument("amount")
49 currency
= self
.get_argument("currency", "EUR")
50 frequency
= self
.get_argument("frequency")
53 locale
= self
.get_browser_locale()
55 # Get organization information
56 if type == "organization":
58 "name" : self
.get_argument("organization"),
59 "vat_number" : self
.get_argument("vat_number", None),
62 # Collect person information
64 "email" : self
.get_argument("email"),
65 "title" : self
.get_argument("title"),
66 "first_name" : self
.get_argument("first_name"),
67 "last_name" : self
.get_argument("last_name"),
68 "locale" : locale
.code
,
71 # Collect address information
73 "street1" : self
.get_argument("street1"),
74 "street2" : self
.get_argument("street2", None),
75 "post_code" : self
.get_argument("post_code"),
76 "city" : self
.get_argument("city"),
77 "state" : self
.get_argument("state", None),
78 "country_code" : self
.get_argument("country_code"),
81 # Send everything to Zeiterfassung
83 # Create a new organization
85 organization
= await self
._create
_organization
(organization
, address
)
88 person
= await self
._create
_person
(person
, address
, organization
)
91 order
= await self
._create
_order
(person
=person
, currency
=currency
)
93 # Add donation to the order
94 await self
._create
_donation
(order
, frequency
, amount
, currency
,
95 vat_included
=(type == "individual"))
98 needs_payment
= await self
._submit
_order
(order
)
102 redirect_url
= await self
._pay
_order
(order
)
104 redirect_url
= "https://%s/donate/thank-you" % self
.request
.host
106 # Redirect the user to the payment page
108 raise tornado
.web
.HTTPError(500, "Did not receive a redirect URL")
110 self
.redirect(redirect_url
)
112 # XXX handle any problems when Zeiterfassung is unreachable
116 async def _create_organization(self
, organization
, address
):
117 # Check if we have an existing organization
118 response
= await self
.backend
.zeiterfassung
.send_request(
119 "/api/v1/organizations/search", **organization
,
122 # Update details if we found a match
124 number
= response
.get("number")
127 await self
.backend
.zeiterfassung
.send_request(
128 "/api/v1/organizations/%s/name" % number
, **organization
132 vat_number
= organization
.get("vat_number", None)
134 await self
.backend
.zeiterfassung
.send_request(
135 "/api/v1/organizations/%s/vat-number" % number
, vat_number
=vat_number
,
139 await self
.backend
.zeiterfassung
.send_request(
140 "/api/v1/organizations/%s/address" % number
, **address
,
145 # Otherwise we will create a new one
146 response
= await self
.backend
.zeiterfassung
.send_request(
147 "/api/v1/organizations/create", **organization
, **address
,
150 # Return the organization's number
151 return response
.get("number")
153 async def _create_person(self
, person
, address
, organization
=None):
155 Searches for a matching person or creates a new one
157 # Check if we have an existing person
158 response
= await self
.backend
.zeiterfassung
.send_request(
159 "/api/v1/persons/search", **person
162 # Update details if we found a match
164 number
= response
.get("number")
167 await self
.backend
.zeiterfassung
.send_request(
168 "/api/v1/persons/%s/name" % number
, **person
,
172 await self
.backend
.zeiterfassung
.send_request(
173 "/api/v1/persons/%s/address" % number
, **address
,
178 # If not, we will create a new one
179 response
= await self
.backend
.zeiterfassung
.send_request(
180 "/api/v1/persons/create", organization
=organization
, **person
, **address
183 # Return the persons's number
184 return response
.get("number")
186 async def _create_order(self
, person
, currency
=None):
188 Creates a new order and returns its ID
190 response
= await self
.backend
.zeiterfassung
.send_request(
191 "/api/v1/orders/create", person
=person
, currency
=currency
,
194 # Return the order number
195 return response
.get("number")
197 async def _create_donation(self
, order
, frequency
, amount
, currency
,
200 Creates a new donation
202 # Select the correct product
204 sku
= SKUS
[frequency
]
208 # Add it to the order
209 await self
.backend
.zeiterfassung
.send_request(
210 "/api/v1/orders/%s/products/add" % order
, sku
=sku
, quantity
=1,
214 await self
.backend
.zeiterfassung
.send_request(
215 "/api/v1/orders/%s/products/%s/price" % (order
, sku
),
216 price
=amount
, currency
=currency
, vat_included
=vat_included
,
219 async def _submit_order(self
, order
):
223 response
= await self
.backend
.zeiterfassung
.send_request(
224 "/api/v1/orders/%s/submit" % order
,
227 # Return whether this needs payment
228 return not response
.get("is_authorized")
230 async def _pay_order(self
, order
):
234 # Add URLs to redirect the user back
236 "success_url" : "https://%s/donate/thank-you" % self
.request
.host
,
237 "error_url" : "https://%s/donate/error" % self
.request
.host
,
238 "back_url" : "https://%s/donate" % self
.request
.host
,
242 response
= await self
.backend
.zeiterfassung
.send_request(
243 "/api/v1/orders/%s/pay" % order
, **urls
,
246 # Return redirect URL
247 return response
.get("redirect_url", None)
250 class ThankYouHandler(base
.BaseHandler
):
252 self
.render("donate/thank-you.html")
255 class ErrorHandler(base
.BaseHandler
):
257 self
.render("donate/error.html")
260 class CheckVATNumberHandler(base
.APIHandler
):
261 @base.ratelimit(minutes
=5, requests
=25)
263 vat_number
= self
.get_argument("vat_number")
266 response
= await self
.backend
.zeiterfassung
.send_request(
267 "/api/v1/organizations/check-vat-number", vat_number
=vat_number
)
269 # Forward the response
270 self
.finish(response
)