def send_payment_notification(): logger.info('Sending payment notification') with transaction.atomic(): finished_purchases = Purchase.objects.filter( payment_status__in=[PaymentStatusName.SUCCESS.value, PaymentStatusName.FAILED.value], confirmation_sent=False ) logger.info('Found: {} finished payments.'.format(finished_purchases.count())) for purchase in finished_purchases: completed = purchase.payment_status == PaymentStatusName.SUCCESS.value subject = 'Purchase completed [{}]'.format(purchase.id) if completed else 'Purchase failed [{}]'.format( purchase.id) user = purchase.user template = 'completed' if completed else 'failed' send_mail.delay( [user.email], subject, get_rendered_template('mail/purchase/{}.txt'.format(template), {'name': user.first_name, 'purchase_id': purchase.id}), get_rendered_template('mail/purchase/{}.html'.format(template), {'name': user.first_name, 'purchase_id': purchase.id}), ['*****@*****.**'] ) purchase.confirmation_sent = True purchase.save()
def send_mail(to, title, messageTXT, messageHTML, bcc=None, attachment=[]): ''' :param to: :param title: :param messageTXT: :param messageHTML: :param bcc: :param attachment: (filename, content, mimetype) :return: ''' logger.info( 'Sending email to: {}, title: {}, messageTXT: {}, messageHTML: {}, bcc: {}, attachment: {}'.format(to, title, messageTXT, messageHTML, bcc, bool( attachment))) email = EmailMultiAlternatives( subject=title, body=messageTXT, from_email='*****@*****.**', to=to, bcc=bcc, attachments=attachment and [attachment] or [] ) email.attach_alternative(messageHTML, "text/html") email.send()
def check_payu_payment_status(): logger.info('Checking payment status.') with transaction.atomic(): pending_purchases = Purchase.objects.filter( payment_status__in=[PaymentStatusName.PENDING.value, PaymentStatusName.STARTED.value], payment_type=PaymentTypeName.PAYU.value ) logger.info('Found: {} pending payments.'.format(pending_purchases.count())) for purchase in pending_purchases: purchase_id = purchase.id logger.info('Checking payment status for purchase: {}, current payment status: {}'.format( purchase_id, purchase.payment_status )) payu_payment = purchase.payu_payment payu_payment_status = payu_payment.payment_status logger.info('Current PayU status: {}, purchase: {}'.format(payu_payment_status, purchase_id)) if payu_payment_status.lower() == PayUPaymentStatus.STATUS_COMPLETED: purchase.payment_status = PaymentStatusName.SUCCESS.value elif payu_payment_status.lower() == PayUPaymentStatus.STATUS_FAILED: purchase.payment_status = PaymentStatusName.FAILED.value elif payu_payment_status.lower() == PayUPaymentStatus.STATUS_STARTED: purchase.payment_status = PaymentStatusName.STARTED.value logger.info('New purchase status: {}, purchase: {}'.format(purchase.payment_status, purchase_id)) purchase.save() return None
def __find_workshops_for_query(query): search_results = SearchQuerySet().models(Workshop).filter(text__in=query.split()).load_all() valid_results = [result for result in search_results if result is not None] for result in valid_results: logger.info('Found result with id: {:<30} and score: {}'.format(result.id, result.score)) return [search_result.object for search_result in search_results]
def _get_or_generate_token(user): try: return Token.objects.get(user=user) except Token.DoesNotExist: logger.info( 'No token found for user: %s. New token will be generated.'.format( user.id)) return Token.objects.create(user=user)
def rebuild_workshops_full_text_search(): logger.info('Updating workshop full-text search index.') try: rebuild_index.Command().handle(using=['default'], verbosity=2, remove=True, noinput=True) except Exception as e: logger.error('Caught exception while updating workshop index: %s' % e) return None
def _calculate_price(user, product, discount): price_net = product.price_net if discount: price_net = int(price_net - (price_net * discount) / 100) logger.info('New price for user: {} is: {}'.format(user.id, price_net)) price_vat_value = product.price_vat price_total = int(price_net + price_net * price_vat_value) logger.info('User: {}, price net: {}, price total: {}'.format(user.id, price_net, price_total)) return (price_net, price_total)
def search_workshops(request, **kwargs): payload = request.DATA __validate_search_workshops_payload(payload) query = payload['query'] logger.info('Looking for workshops for query: {}'.format(query)) workshops = __find_workshops_for_query(query) return prepare_list_of_workshops_response(workshops)
def __execute_post_request(headers, request_content, url): response = requests.post(url, data=request_content, headers=headers) response_dict = json.loads(response.content.decode("utf-8"), 'utf-8') if "response" not in response_dict: raise PythonIfirmaExceptionFactory.throw_exception_by_code(-1) real_response_content = response_dict["response"] logger.info('ifirma response: {}'.format(real_response_content)) response_code = real_response_content.get("Kod", -1) if response_code != 0: raise PythonIfirmaExceptionFactory.throw_exception_by_code(response_code) return response_dict
def _get_purchase_invoice_data_or_none(purchase): try: invoice = PurchaseInvoice.objects.get(purchase=purchase) return { 'name': invoice.name, 'street': invoice.street, 'city': invoice.city, 'zipCode': invoice.zip_code, 'country': invoice.country, 'taxId': invoice.tax_id, } except PurchaseInvoice.DoesNotExist as e: logger.info('Skipping invoice processing, no invoice for purchase: {}, err: {}'.format(purchase.id, str(e))) return None
def __execute_post_request(headers, request_content, url): response = requests.post(url, data=request_content, headers=headers) response_dict = json.loads(response.content.decode("utf-8"), 'utf-8') if "response" not in response_dict: raise PythonIfirmaExceptionFactory.throw_exception_by_code(-1) real_response_content = response_dict["response"] logger.info('ifirma response: {}'.format(real_response_content)) response_code = real_response_content.get("Kod", -1) if response_code != 0: raise PythonIfirmaExceptionFactory.throw_exception_by_code( response_code) return response_dict
def delete_workshop_message(request, **kwargs): workshop_id = kwargs['workshop_id'] find_workshop_for_id_or_raise(workshop_id) message_id = kwargs['message_id'] message = find_message_for_id_or_raise(message_id) user = request.user _check_if_user_is_author_of_message_or_workshop_mentor(message, user) logger.info('User with ID: {}, deletes messages with ID: {}'.format(user.id, message.id)) message.delete() return Response(status=HTTP_204_NO_CONTENT)
def reset_pass_initialize(request, **kwargs): payload = request.DATA validate_payload_with_schema(payload, reset_pass_initialize_req_schema) email = payload['email'] logger.info('Starting reset password process for: {}'.format(email)) user = __find_user_auth_for_email(email) if user is not None: __remove_previous_reset_pw_attempts(email) reset_pw = __create_new_reset_password(email) reset_pw_link = __prepare_reset_pw_link(reset_pw.token) __send_reset_pw_email(email, reset_pw_link) return Response(status=HTTP_204_NO_CONTENT)
def __check_if_user_has_successful_purchase(user, workshop_id): try: return Purchase.objects.get(user=user, payment_status=PaymentStatusName.SUCCESS.value) except Purchase.DoesNotExist as e: logger.error( 'No purchase found for user with ID: {} when signing for workshop with ID: {}, err: {}'.format( user.id, workshop_id, str(e)) ) try: purchase = Purchase.objects.get(user=user) logger.info('User with ID: {} has purchase with ID: {}, status: {}, payment type: {}'.format( user.id, purchase.id, purchase.payment_status, purchase.payment_type) ) except Purchase.DoesNotExist: pass raise WorkshopWithoutPurchaseSignAttemptException(user.id)
def __check_if_tickets_limit_exceeded_but_honor_100_discount(promo_code): all_purchases = _count_success_purchases() organizers_purchases = _count_organizers_purchases() volunteers_purchases = _count_volunteers_purchases() speakers_purchases = _count_speakers_purchases() sponsors_staff_purchases = _count_sponsors_staff_purchases() sum_excluded = sum([organizers_purchases, volunteers_purchases, speakers_purchases, sponsors_staff_purchases, ]) purchases_limit = settings.MAX_TICKETS logger.info( 'Success purchases: {}, sum excluded: {}, free: {}'.format(all_purchases, sum_excluded, purchases_limit - all_purchases + sum_excluded) ) is_100_discount = __is_100_discount_promo_code(promo_code) if ((all_purchases - sum_excluded) >= purchases_limit) and (not is_100_discount): raise TicketsLimitExceededException()
def generate_and_send_invoice(): logger.info('Generating and sending invoices.') unsent_invoices = PurchaseInvoice.objects.filter( sent=False, purchase__payment_status=PaymentStatusName.SUCCESS.value, purchase__confirmation_sent=True ) logger.info('Found: {} unsent invoices.'.format(unsent_invoices.count())) for invoice in unsent_invoices: with transaction.atomic(): try: purchase = invoice.purchase logger.info('Generating invoice for purchase: {}'.format(purchase.id)) client = iFirmaClient( invoice.name, invoice.tax_id, iFirmaAddress( invoice.city, invoice.zip_code, invoice.street, invoice.country, ) ) position = iFirmaItem( VAT.VAT_23, 1, float("{0:.2f}".format(purchase.price_total / 100.0)), u"Bilet wstępu na warsztaty codepot.pl: {}".format(purchase.id), "szt." ) ifirma_invoice = iFirmaInvoiceParams(client, [position]) (ifirma_invoice_id, ifirma_invoice_no) = _ifirma_client.generate_invoice(ifirma_invoice) ifirma_invoice_pdf = _ifirma_client.get_invoice_pdf(ifirma_invoice_id) invoice.ifirma_id = ifirma_invoice_id send_mail( [purchase.user.email], 'Payment completed [{}]'.format(purchase.id), get_rendered_template( 'mail/purchase/invoice.txt', {'name': purchase.user.first_name, 'purchase_id': purchase.id} ), get_rendered_template( 'mail/purchase/invoice.html', {'name': purchase.user.first_name, 'purchase_id': purchase.id} ), ['*****@*****.**'], ('{}.pdf'.format(ifirma_invoice_no), ifirma_invoice_pdf.getvalue(), 'application/pdf') ) invoice.no = ifirma_invoice_no invoice.sent = True invoice.save() except Exception as e: logger.error('Error while generating invoice for purchase: {}, err: {}.'.format(purchase.id, str(e))) continue
def save(self, *args, **kwargs): if self.usage_limit == 0: self.active = False logger.info('Setting promo code: {} to inactive.'.format( self.code)) super(PromoCode, self).save(*args, **kwargs)
def i(msg): logger.info(msg)
def _update_workshop_full_text_search_index(**kwargs): logger.info('Rebuilding workshops full text search index.') rebuild_workshops_full_text_search.delay()
def _get_or_generate_token(user): try: return Token.objects.get(user=user) except Token.DoesNotExist: logger.info('No token found for user: %s. New token will be generated.'.format(user.id)) return Token.objects.create(user=user)
def handle_new_purchase(request, **kwargs): _check_if_registration_open() payload = request.DATA code = payload['promoCode'] __check_if_tickets_limit_exceeded_but_honor_100_discount(code) user = request.user _check_if_user_has_purchase(user) logger.info('Handling new purchase for user: {} and payload: {}'.format(user.id, payload)) invoice = payload['invoice'] product_id = payload['productId'] payment_type = payload['paymentType'] payment_req_info = payload['paymentInfo'] product = _find_and_validate_product(product_id) _validate_payment_info(payment_type, payment_req_info) _increment_tickets_purchased(product.price_tier) purchase = Purchase() purchase.user = user purchase.payment_type = payment_type purchase.product = product purchase.payment_status = PaymentStatusName.PENDING.value purchase.save() discount = None if code: promo_code = _find_and_validate_promo_code(code) purchase.promo_code = promo_code promo_code.usage_limit -= 1 promo_code.save() discount = promo_code.discount logger.info('Found promo code: {} for user: {}, discount: {}'.format(code, user.id, discount)) if discount == 100: logger.info('Found 100% discount for user: {} and promo code: {}'.format(user.id, code)) classification = promo_code.classification is_group_purchase = classification and classification.name.startswith('group') or False purchase.payment_type = is_group_purchase and PaymentTypeName.GROUP.value or PaymentTypeName.FREE.value purchase.payment_status = PaymentStatusName.SUCCESS.value purchase.save() return Response(build_purchase_response(purchase), HTTP_201_CREATED) if invoice: _set_invoice_data(purchase, invoice) (price_net, price_total) = _calculate_price(user, product, discount) purchase.price_net = price_net purchase.price_total = price_total if payment_type == PaymentTypeName.PAYU.value: redirect_link = payment_req_info['redirectLink'] _handle_payu_payment(user, request.META['REMOTE_ADDR'], price_total, purchase, redirect_link) elif payment_type == PaymentTypeName.TRANSFER.value: purchase.notes = 'To pay net: {}, total: {}'.format(price_net, price_total) purchase.payu_payment = None purchase.save() return Response(build_purchase_response(purchase), HTTP_201_CREATED)
def save(self, *args, **kwargs): if self.usage_limit == 0: self.active = False logger.info('Setting promo code: {} to inactive.'.format(self.code)) super(PromoCode, self).save(*args, **kwargs)