|
51 | 51 | HttpResponseRedirect,
|
52 | 52 | JsonResponse,
|
53 | 53 | )
|
| 54 | +from django.middleware.csrf import get_token |
54 | 55 | from django.shortcuts import get_object_or_404, redirect
|
55 | 56 | from django.template.loader import render_to_string
|
56 | 57 | from django.urls import reverse
|
@@ -1322,6 +1323,78 @@ def post(self, request, *args, **kwargs):
|
1322 | 1323 | return JsonResponse({"result": "success"})
|
1323 | 1324 |
|
1324 | 1325 |
|
| 1326 | +class AuctionTOSValidation(AuctionViewMixin, APIPostView): |
| 1327 | + """For real time validation on the auctiontos admin create form |
| 1328 | + See views.AuctionTOSAdmin for the corresponding js and view |
| 1329 | + qqq""" |
| 1330 | + |
| 1331 | + def post(self, request, *args, **kwargs): |
| 1332 | + pk = request.POST.get("pk", None) |
| 1333 | + try: |
| 1334 | + pk = int(pk) if pk is not None else None |
| 1335 | + except ValueError: |
| 1336 | + pk = None |
| 1337 | + name = request.POST.get("name", None) |
| 1338 | + bidder_number = request.POST.get("bidder_number", None) |
| 1339 | + email = request.POST.get("email", None) |
| 1340 | + # note: be careful what you dump in result |
| 1341 | + # javascript will fill out any id on the form with this info |
| 1342 | + result = { |
| 1343 | + "id_bidder_number": "", |
| 1344 | + "id_name": "", |
| 1345 | + "id_email": "", |
| 1346 | + "id_address": "", |
| 1347 | + "id_is_club_member": "", |
| 1348 | + "id_phone_number": "", |
| 1349 | + "id_memo": "", |
| 1350 | + "name_tooltip": "", |
| 1351 | + "bidder_number_tooltip": "", |
| 1352 | + "email_tooltip": "", |
| 1353 | + } |
| 1354 | + base_qs = self.auction.tos_qs |
| 1355 | + if pk: |
| 1356 | + base_qs = base_qs.exclude(pk=pk) |
| 1357 | + if name and not email and not pk: |
| 1358 | + old_auctions = Auction.objects.filter( |
| 1359 | + Q(created_by=self.auction.created_by) |
| 1360 | + | Q(created_by=self.request.user) |
| 1361 | + | Q(auctiontos__is_admin=True, auctiontos__user=self.request.user) |
| 1362 | + ) |
| 1363 | + qs = AuctionTOS.objects.filter(auction__in=old_auctions, email__isnull=False).order_by("-createdon") |
| 1364 | + old_tos = AuctionTOSFilter.generic(self, qs, name, match_names_only=True).first() |
| 1365 | + if old_tos: |
| 1366 | + bidder_number_used_in_this_auction = base_qs.filter(bidder_number=old_tos.bidder_number).first() |
| 1367 | + if not bidder_number_used_in_this_auction: |
| 1368 | + result["id_bidder_number"] = old_tos.bidder_number |
| 1369 | + result["id_name"] = old_tos.name |
| 1370 | + result["id_email"] = old_tos.email |
| 1371 | + result["id_address"] = old_tos.address |
| 1372 | + result["id_is_club_member"] = old_tos.is_club_member |
| 1373 | + result["id_phone_number"] = old_tos.phone_number |
| 1374 | + result["id_memo"] = old_tos.memo |
| 1375 | + else: |
| 1376 | + logger.info("no user found in older auctions with name %s", name) |
| 1377 | + if name: |
| 1378 | + existing_tos_in_this_auction = AuctionTOSFilter.generic(self, base_qs, name, match_names_only=True).first() |
| 1379 | + if existing_tos_in_this_auction: |
| 1380 | + result["name_tooltip"] = f"{existing_tos_in_this_auction.name} is already in this auction" |
| 1381 | + else: |
| 1382 | + logger.info("no user found in older auctions with name %s", name) |
| 1383 | + if email: |
| 1384 | + existing_tos_in_this_auction = base_qs.filter(email=email).first() |
| 1385 | + if existing_tos_in_this_auction: |
| 1386 | + result["email_tooltip"] = "Email is already in this auction" |
| 1387 | + else: |
| 1388 | + logger.info("no user found in this auction with email %s", email) |
| 1389 | + if bidder_number: |
| 1390 | + existing_tos_in_this_auction = base_qs.filter(bidder_number=bidder_number).first() |
| 1391 | + if existing_tos_in_this_auction: |
| 1392 | + result["bidder_number_tooltip"] = "Bidder number in use" |
| 1393 | + else: |
| 1394 | + logger.info("no user found in this auction with email %s", email) |
| 1395 | + return JsonResponse(result) |
| 1396 | + |
| 1397 | + |
1325 | 1398 | @login_required
|
1326 | 1399 | def my_won_lot_csv(request):
|
1327 | 1400 | """CSV file showing won lots"""
|
@@ -1658,7 +1731,9 @@ def auctionLotList(request, slug):
|
1658 | 1731 | first_row_fields.append(auction.custom_field_1_name)
|
1659 | 1732 | writer.writerow(first_row_fields)
|
1660 | 1733 | # lots = Lot.objects.exclude(is_deleted=True).filter(auction__slug=slug, auctiontos_winner__isnull=False).select_related('user', 'winner')
|
1661 |
| - lots = auction.lots_qs.filter(winning_price__isnull=False).select_related("user", "winner") |
| 1734 | + lots = auction.lots_qs.filter(winning_price__isnull=False, auctiontos_winner__isnull=False).select_related( |
| 1735 | + "user", "winner" |
| 1736 | + ) |
1662 | 1737 | lots = add_price_info(lots)
|
1663 | 1738 | for lot in lots:
|
1664 | 1739 | row = [
|
@@ -4001,10 +4076,151 @@ def get_context_data(self, **kwargs):
|
4001 | 4076 | # for real time form validation
|
4002 | 4077 | extra_script = "<script>"
|
4003 | 4078 | if self.auctiontos:
|
4004 |
| - extra_script += f"let pk={self.auctiontos.pk};" |
| 4079 | + extra_script += f"var pk={self.auctiontos.pk};" |
4005 | 4080 | else:
|
4006 |
| - extra_script += "let pk=null;" |
4007 |
| - extra_script += "console.log(pk);</script>" |
| 4081 | + extra_script += "var pk=null;" |
| 4082 | + extra_script += f"""var validation_url = '{reverse('auctiontos_validation', kwargs={'slug': self.auction.slug})}'; |
| 4083 | + var csrf_token = '{get_token(self.request)}';'qqq'""" |
| 4084 | + extra_script += """ |
| 4085 | +
|
| 4086 | + function setFieldInvalid(fieldId, message, is_invalid) { |
| 4087 | + var field = document.getElementById(fieldId); |
| 4088 | + if (!field) return; |
| 4089 | +
|
| 4090 | + var feedbackId = fieldId + "_feedback"; |
| 4091 | + var feedback = document.getElementById(feedbackId); |
| 4092 | +
|
| 4093 | + if (is_invalid) { |
| 4094 | + field.classList.add("is-invalid"); |
| 4095 | + var existing_error = document.getElementById( "error_1_"+fieldId); |
| 4096 | + if (existing_error) { |
| 4097 | + existing_error.remove(); |
| 4098 | + } |
| 4099 | + if (feedback) { |
| 4100 | + feedback.remove(); |
| 4101 | + } |
| 4102 | + feedback = document.createElement("div"); |
| 4103 | + feedback.id = feedbackId; |
| 4104 | + feedback.className = "invalid-feedback"; |
| 4105 | + field.parentNode.appendChild(feedback); |
| 4106 | +
|
| 4107 | + feedback.textContent = message; |
| 4108 | + } else { |
| 4109 | + field.classList.remove("is-invalid"); |
| 4110 | + if (feedback) { |
| 4111 | + feedback.remove(); |
| 4112 | + } |
| 4113 | + } |
| 4114 | + } |
| 4115 | +
|
| 4116 | + function showAutocomplete(response, remove) { |
| 4117 | + var feedback = document.getElementById('id_name_feedback'); |
| 4118 | + if (feedback) { |
| 4119 | + feedback.remove(); |
| 4120 | + } |
| 4121 | + if (remove) { |
| 4122 | + return; |
| 4123 | + } |
| 4124 | + feedback = document.createElement("div"); |
| 4125 | + feedback.id = "id_name_feedback"; |
| 4126 | + feedback.className = "valid-feedback d-block cursor-pointer"; |
| 4127 | + feedback.innerHTML = "<button role='button' class='btn btn-sm btn-info' id='autocompleteTosForm'>Click to use " + response.id_email + "</button>"; |
| 4128 | + var autocomplete = response; |
| 4129 | + document.getElementById('id_name').parentNode.appendChild(feedback); |
| 4130 | +
|
| 4131 | + //setTimeout(function() { |
| 4132 | + var link = document.getElementById('autocompleteTosForm'); |
| 4133 | + link.addEventListener('click', function(event) { |
| 4134 | + event.preventDefault(); |
| 4135 | +
|
| 4136 | + for (var key in autocomplete) { |
| 4137 | + console.log(key); |
| 4138 | + if (autocomplete.hasOwnProperty(key)) { |
| 4139 | + var element = document.getElementById(key); |
| 4140 | + if (element) { |
| 4141 | + if (element.type !== "checkbox" && element.value === "") { |
| 4142 | + element.value = autocomplete[key] || ''; |
| 4143 | + } |
| 4144 | + if (element.type === "checkbox") { |
| 4145 | + element.checked = autocomplete[key] === true; |
| 4146 | + } |
| 4147 | + } |
| 4148 | + } |
| 4149 | + } |
| 4150 | +
|
| 4151 | + }); |
| 4152 | + link.focus(); |
| 4153 | + //}, 40); |
| 4154 | +
|
| 4155 | + } |
| 4156 | +
|
| 4157 | +
|
| 4158 | + function showTooltip(element, message) { |
| 4159 | + var el = element; |
| 4160 | +
|
| 4161 | + // Destroy existing tooltip (if any) |
| 4162 | + if (el._tooltipInstance) { |
| 4163 | + el._tooltipInstance.dispose(); |
| 4164 | + } |
| 4165 | +
|
| 4166 | + // Set tooltip attributes |
| 4167 | + el.setAttribute("data-bs-toggle", "tooltip"); |
| 4168 | + el.setAttribute("data-bs-placement", "right"); |
| 4169 | + el.setAttribute("title", message); |
| 4170 | +
|
| 4171 | + // Initialize and show Bootstrap tooltip |
| 4172 | + el._tooltipInstance = new bootstrap.Tooltip(el); |
| 4173 | + el._tooltipInstance.show(); |
| 4174 | + } |
| 4175 | +
|
| 4176 | + function hideTooltip(element) { |
| 4177 | + if (element._tooltipInstance) { |
| 4178 | + element._tooltipInstance.dispose(); |
| 4179 | + element._tooltipInstance = null; |
| 4180 | + } |
| 4181 | + } |
| 4182 | +
|
| 4183 | + function validateField() { |
| 4184 | + var nameInput = document.getElementById("id_name"); |
| 4185 | +
|
| 4186 | + var data = { |
| 4187 | + pk: pk, |
| 4188 | + name: $("#id_name").val(), |
| 4189 | + bidder_number: $("#id_bidder_number").val(), |
| 4190 | + email: $("#id_email").val(), |
| 4191 | + }; |
| 4192 | +
|
| 4193 | + $.ajax({ |
| 4194 | + url: validation_url, |
| 4195 | + type: "POST", |
| 4196 | + data: data, |
| 4197 | + headers: { "X-CSRFToken": csrf_token }, |
| 4198 | + success: function (response) { |
| 4199 | + if (response.name_tooltip) { |
| 4200 | + showTooltip(nameInput, response.name_tooltip); |
| 4201 | + showAutocomplete(response, true) |
| 4202 | + } else if (response.id_email) { |
| 4203 | + showAutocomplete(response) |
| 4204 | + } else { |
| 4205 | + hideTooltip(nameInput); |
| 4206 | + showAutocomplete(response, true) |
| 4207 | + } |
| 4208 | + if (response.email_tooltip) { |
| 4209 | + setFieldInvalid("id_email", response.email_tooltip, true); |
| 4210 | + } else { |
| 4211 | + setFieldInvalid("id_email", response.email_tooltip, false); |
| 4212 | + } |
| 4213 | + if (response.bidder_number_tooltip) { |
| 4214 | + setFieldInvalid("id_bidder_number", response.bidder_number_tooltip, true); |
| 4215 | + } else { |
| 4216 | + setFieldInvalid("id_bidder_number", response.bidder_number_tooltip, false); |
| 4217 | + } |
| 4218 | + } |
| 4219 | + }); |
| 4220 | + } |
| 4221 | +
|
| 4222 | + $("#id_bidder_number, #id_name, #id_email").on("blur", validateField); |
| 4223 | + </script>""" |
4008 | 4224 | context["extra_script"] = mark_safe(extra_script)
|
4009 | 4225 | return context
|
4010 | 4226 |
|
@@ -5157,7 +5373,7 @@ def get_queryset(self):
|
5157 | 5373 |
|
5158 | 5374 | def dispatch(self, request, *args, **kwargs):
|
5159 | 5375 | self.lot = get_object_or_404(Lot, pk=kwargs.pop("pk"), is_deleted=False)
|
5160 |
| - self.filename = "label_" + self.lot.custom_lot_number |
| 5376 | + self.filename = f"label_{self.lot.lot_number_display}" |
5161 | 5377 | if self.lot.auctiontos_seller:
|
5162 | 5378 | self.auction = self.lot.auctiontos_seller.auction
|
5163 | 5379 | auth = False
|
|
0 commit comments