]>
git.ipfire.org Git - ipfire.org.git/blob - src/web/donate.py
10 "monthly" : "IPFIRE-DONATION-MONTHLY",
11 "quarterly" : "IPFIRE-DONATION-QUARTERLY",
12 "yearly" : "IPFIRE-DONATION-YEARLY",
14 DEFAULT_SKU
= "IPFIRE-DONATION"
16 class DonateHandler(auth
.CacheMixin
, base
.BaseHandler
):
18 country
= self
.current_country_code
21 first_name
= self
.get_argument("first_name", None)
22 last_name
= self
.get_argument("last_name", None)
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
, first_name
=first_name
, last_name
=last_name
,
41 amount
=amount
, currency
=currency
, frequency
=frequency
)
43 @base.ratelimit(minutes
=15, requests
=5)
45 type = self
.get_argument("type")
46 if not type in ("individual", "organization"):
47 raise tornado
.web
.HTTPError(400, "type is of an invalid value: %s" % type)
49 amount
= self
.get_argument("amount")
50 currency
= self
.get_argument("currency", "EUR")
51 frequency
= self
.get_argument("frequency")
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"),
70 # Collect address information
72 "street1" : self
.get_argument("street1"),
73 "street2" : self
.get_argument("street2", None),
74 "post_code" : self
.get_argument("post_code"),
75 "city" : self
.get_argument("city"),
76 "state" : self
.get_argument("state", None),
77 "country_code" : self
.get_argument("country_code"),
80 # Send everything to Zeiterfassung
82 # Create a new organization
84 organization
= await self
._create
_organization
(organization
, address
)
87 person
= await self
._create
_person
(person
, address
, organization
)
90 order
= await self
._create
_order
(person
=person
, currency
=currency
)
92 # Add donation to the order
93 await self
._create
_donation
(order
, frequency
, amount
, currency
,
94 vat_included
=(type == "individual"))
97 needs_payment
= await self
._submit
_order
(order
)
101 redirect_url
= await self
._pay
_order
(order
)
103 redirect_url
= "https://%s/donate/thank-you" % self
.request
.host
105 # Redirect the user to the payment page
107 raise tornado
.web
.HTTPError(500, "Did not receive a redirect URL")
109 self
.redirect(redirect_url
)
111 # XXX handle any problems when Zeiterfassung is unreachable
115 async def _create_organization(self
, organization
, address
):
116 # Check if we have an existing organization
117 response
= await self
.backend
.zeiterfassung
.send_request(
118 "/api/v1/organizations/search", **organization
,
121 # Update details if we found a match
123 number
= response
.get("number")
126 await self
.backend
.zeiterfassung
.send_request(
127 "/api/v1/organizations/%s/name" % number
, **organization
131 vat_number
= organization
.get("vat_number", None)
133 await self
.backend
.zeiterfassung
.send_request(
134 "/api/v1/organizations/%s/vat-number" % number
, vat_number
=vat_number
,
138 await self
.backend
.zeiterfassung
.send_request(
139 "/api/v1/organizations/%s/address" % number
, **address
,
144 # Otherwise we will create a new one
145 response
= await self
.backend
.zeiterfassung
.send_request(
146 "/api/v1/organizations/create", **organization
, **address
,
149 # Return the organization's number
150 return response
.get("number")
152 async def _create_person(self
, person
, address
, organization
=None):
154 Searches for a matching person or creates a new one
156 # Check if we have an existing person
157 response
= await self
.backend
.zeiterfassung
.send_request(
158 "/api/v1/persons/search", **person
161 # Update details if we found a match
163 number
= response
.get("number")
166 await self
.backend
.zeiterfassung
.send_request(
167 "/api/v1/persons/%s/name" % number
, **person
,
171 await self
.backend
.zeiterfassung
.send_request(
172 "/api/v1/persons/%s/address" % number
, **address
,
177 # If not, we will create a new one
178 response
= await self
.backend
.zeiterfassung
.send_request(
179 "/api/v1/persons/create", organization
=organization
, **person
, **address
182 # Return the persons's number
183 return response
.get("number")
185 async def _create_order(self
, person
, currency
=None):
187 Creates a new order and returns its ID
189 response
= await self
.backend
.zeiterfassung
.send_request(
190 "/api/v1/orders/create", person
=person
, currency
=currency
,
193 # Return the order number
194 return response
.get("number")
196 async def _create_donation(self
, order
, frequency
, amount
, currency
,
199 Creates a new donation
201 # Select the correct product
203 sku
= SKUS
[frequency
]
207 # Add it to the order
208 await self
.backend
.zeiterfassung
.send_request(
209 "/api/v1/orders/%s/products/add" % order
, sku
=sku
, quantity
=1,
213 await self
.backend
.zeiterfassung
.send_request(
214 "/api/v1/orders/%s/products/%s/price" % (order
, sku
),
215 price
=amount
, currency
=currency
, vat_included
=vat_included
,
218 async def _submit_order(self
, order
):
222 response
= await self
.backend
.zeiterfassung
.send_request(
223 "/api/v1/orders/%s/submit" % order
,
226 # Return whether this needs payment
227 return not response
.get("is_authorized")
229 async def _pay_order(self
, order
):
233 # Add URLs to redirect the user back
235 "success_url" : "https://%s/donate/thank-you" % self
.request
.host
,
236 "error_url" : "https://%s/donate/error" % self
.request
.host
,
237 "back_url" : "https://%s/donate" % self
.request
.host
,
241 response
= await self
.backend
.zeiterfassung
.send_request(
242 "/api/v1/orders/%s/pay" % order
, **urls
,
245 # Return redirect URL
246 return response
.get("redirect_url", None)
249 class ThankYouHandler(base
.BaseHandler
):
251 self
.render("donate/thank-you.html")
254 class ErrorHandler(base
.BaseHandler
):
256 self
.render("donate/error.html")