def send_ride_mails(self): if self.rides_mails_sent is True: log_event(event="Not sending ride mails for round %d because " "rides_mails_sent is True" % self.pk) return log_event(event="Sending ride mails for round %d" % self.pk) mail_template = get_template_by_id(config.RIDE_MAIL) self.rides_mails_sent = True self.save() rides = self.rides.all() for ride in rides: involved = { ride.driver, ride.codriver, self.distribution_coordinator } for user in involved: if user is None: continue rendered_template_vars = render_mail_template( mail_template, user=user, ride=ride, base_url=settings.BASE_URL) mail_user(user, *rendered_template_vars)
def send_ride_mails(self): if self.rides_mails_sent is True: log_event(event="Not sending ride mails for round %d because " "rides_mails_sent is True" % self.pk) return log_event(event="Sending ride mails for round %d" % self.pk) mail_template = get_template_by_id(config.RIDE_MAIL) self.rides_mails_sent = True self.save() rides = self.rides.all() for ride in rides: involved = { ride.driver, ride.codriver, self.distribution_coordinator } for user in involved: if user is None: continue rendered_template_vars = render_mail_template( mail_template, user=user, ride=ride, base_url=settings.BASE_URL ) mail_user(user, *rendered_template_vars)
def mail_user(user, subject, html_body, plain_body): send_mail(subject=subject, message=plain_body, from_email="VOKO Utrecht <*****@*****.**>", recipient_list=["%s <%s>" % (user.get_full_name(), user.email)], html_message=html_body) log.log_event(user=user, event="Mail sent: %s" % subject, extra=html_body)
def post(self, request, *args, **kwargs): order = self.get_object() user_notes = request.POST.get('notes').strip() if user_notes: order.user_notes = user_notes log_event(event="Finalizing order %s" % order.id, user=order.user) order.finalized = True # Freeze order order.save() if self.calculate_payment() == 0: log_event( event="Payment for order %d not necessary because order total " "is %f and user's credit is %f" % (order.id, order.total_price, order.user.balance.credit()), user=order.user ) self._message_payment_unnecessary() order.complete_after_payment() return redirect(reverse('order_summary', args=(order.pk,))) return redirect('finance.choosebank')
def save(self, commit=True): with transaction.atomic(): # Update user user = super(ChangeProfileForm, self).save() if self.cleaned_data['password1']: user.set_password(self.cleaned_data["password1"]) # Profile userprofile = user.userprofile userprofile.phone_number = self.cleaned_data['phone_number'] userprofile.has_drivers_license = ( self.cleaned_data['has_drivers_license']) userprofile.contact_person = self.cleaned_data['contact_person'] userprofile.shares_car = self.cleaned_data['shares_car'] userprofile.car_neighborhood = ( self.cleaned_data['car_neighborhood']) userprofile.car_type = self.cleaned_data['car_type'] if commit: user.save() userprofile.save() log.log_event(user=user, event="User changed profile") return user
def send_prepare_ride_mails(self): if self.prepare_ride_mails_sent is True: log_event(event="Not sending prepare ride mails for round %d " "because prepare_ride_mails_sent is True" % self.pk) return log_event(event="Sending prepare ride mails for round %d" % self.pk) mail_template = get_template_by_id(config.PREPARE_RIDE_MAIL) self.prepare_ride_mails_sent = True self.save() rides = self.rides.all() for ride in rides: drivers = [ride.driver, ride.codriver] for user in drivers: rendered_template_vars = render_mail_template( mail_template, user=user, ride=ride, base_url=settings.BASE_URL ) mail_user(user, *rendered_template_vars)
def force_confirm_email(modeladmin, request, queryset): for user in queryset: user.email_confirmation.is_confirmed = True user.email_confirmation.save() log.log_event(operator=request.user, event="User's e-mail forcefully confirmed: %s" % user, user=user)
def mail_user(user, subject, html_body, plain_body, from_email): default_from_email = settings.DEFAULT_FROM_EMAIL send_mail(subject=subject, message=plain_body, from_email=from_email if from_email else default_from_email, recipient_list=["%s <%s>" % (user.get_full_name(), user.email)], html_message=html_body) log.log_event(user=user, event="Mail sent: %s" % subject, extra=html_body)
def complete_after_payment(self): """ Complete order by setting the 'paid' boolean, creating debit and mailing the user. """ log_event(event="Completing (paid) order %s" % self.id, user=self.user) self.paid = True self.save() self.create_debit() self.mail_confirmation()
def create_debit(self): """ Create debit for order and create one-to-one relation """ log_event(event="Creating debit for order %s" % self.id) self.debit = Balance.objects.create(user=self.user, type="DR", amount=self.total_price, notes="Debit van %s voor bestelling #%d" % (self.total_price, self.pk)) self.save()
def complete_after_payment(self): """ Complete order by setting the 'paid' boolean, creating debit and mailing the user. """ log_event(event="Completing (paid) order %s" % self.id, user=self.user) with transaction.atomic(): self.paid = True self.save() self.create_debit() self.mail_confirmation()
def create_debit(self): """ Create debit for order and create one-to-one relation """ log_event(event="Creating debit for order %s" % self.id) self.debit = Balance.objects.create( user=self.user, type="DR", amount=self.total_price, notes="Debit van %s voor bestelling #%d" % (self.total_price, self.pk)) self.save()
def post(self, request, *args, **kwargs): Form = self.get_form_class() form = Form(data=request.POST) form.full_clean() if form.is_valid() is False: # Should not happen, as the form has just one input field. # Redirect back to previous view return redirect(reverse('finance.choosebank')) order_to_pay = get_order_to_pay(request.user) if not order_to_pay: messages.error(request, "Geen bestelling gevonden") return redirect(reverse('view_products')) amount_to_pay = order_to_pay\ .total_price_to_pay_with_balances_taken_into_account() log_event( event="Initiating payment (creating transaction) for order %d " "and amount %f" % (order_to_pay.id, amount_to_pay), user=order_to_pay.user) # Sanity checks. If one of these fails, it's very likely that someone # is tampering. assert order_to_pay.user == request.user assert order_to_pay.finalized is True assert order_to_pay.paid is False assert order_to_pay.payments.filter(succeeded=True).exists() is False if order_to_pay.order_round.is_open is not True: messages.error(request, "De bestelronde is gesloten, " "je kunt niet meer betalen.") log_event( event="Payment for order %s canceled because " "order round %s is closed" % (order_to_pay.id, order_to_pay.order_round.id), user=order_to_pay.user) return redirect(reverse('finish_order', args=(order_to_pay.id,))) bank_id = form.cleaned_data['bank'] results = self.create_payment(amount=float(amount_to_pay), description="VOKO Utrecht %d" % order_to_pay.id, issuer_id=bank_id, order_id=order_to_pay.id) Payment.objects.create(amount=amount_to_pay, order=order_to_pay, mollie_id=results["id"]) redirect_url = results.getPaymentUrl() return redirect(redirect_url)
def form_valid(self, form): try: user = VokoUser.objects.get(email=form.cleaned_data['email'].lower()) request = PasswordResetRequest(user=user) request.save() request.send_email() except VokoUser.DoesNotExist: # Do not notify user log.log_event(event="Password reset requested for unknown email address: %s" % form.cleaned_data['email']) return super(RequestPasswordResetView, self).form_valid(form)
def post(self, request, *args, **kwargs): Form = self.get_form_class() form = Form(data=request.POST) form.full_clean() if form.is_valid() is False: # Should not happen, as the form has just one input field. # Redirect back to previous view return redirect(reverse('finance.choosebank')) order_to_pay = get_order_to_pay(request.user) if not order_to_pay: messages.error(request, "Geen bestelling gevonden") return redirect(reverse('view_products')) amount_to_pay = order_to_pay\ .total_price_to_pay_with_balances_taken_into_account() log_event( event="Initiating payment (creating transaction) for order %d " "and amount %f" % (order_to_pay.id, amount_to_pay), user=order_to_pay.user) # Sanity checks. If one of these fails, it's very likely that someone # is tampering. assert order_to_pay.user == request.user assert order_to_pay.finalized is True assert order_to_pay.paid is False assert order_to_pay.payments.filter(succeeded=True).exists() is False if order_to_pay.order_round.is_open is not True: messages.error( request, "De bestelronde is gesloten, " "je kunt niet meer betalen.") log_event(event="Payment for order %s canceled because " "order round %s is closed" % (order_to_pay.id, order_to_pay.order_round.id), user=order_to_pay.user) return redirect(reverse('finish_order', args=(order_to_pay.id, ))) bank_id = form.cleaned_data['bank'] results = self.create_payment(amount=float(amount_to_pay), description="VOKO Utrecht %d" % order_to_pay.id, issuer_id=bank_id, order_id=order_to_pay.id) Payment.objects.create(amount=amount_to_pay, order=order_to_pay, mollie_id=results["id"]) redirect_url = results.getPaymentUrl() return redirect(redirect_url)
def _send_mails(self): for user in self.users: (subject, html_message, plain_message, from_email) = render_mail_template( self.template, user=user, order_round=self.current_order_round) mail_user(user, subject, html_message, plain_message, from_email) log_event(operator=self.request.user, user=user, event="Mail verstuurd met onderwerp '%s'" % subject, extra=html_message)
def form_valid(self, form): try: user = VokoUser.objects.get( email=form.cleaned_data['email'].lower()) request = PasswordResetRequest(user=user) request.save() request.send_email() except VokoUser.DoesNotExist: # Do not notify user log.log_event( event="Password reset requested for unknown email address: %s" % form.cleaned_data['email']) return super(RequestPasswordResetView, self).form_valid(form)
def get(self, request, *args, **kwargs): order_to_pay = Order.objects.get(id=request.session['order_to_pay']) # Sanity checks assert order_to_pay.finalized is True assert order_to_pay.paid is False order_to_pay.finalized = False order_to_pay.save() log_event(event="Payment for order %s canceled" % order_to_pay.id, user=order_to_pay.user) return HttpResponseRedirect( reverse("finish_order", args=(order_to_pay.pk,)))
def _send_mails(self): for user in self.users: subject, html_message, plain_message = render_mail_template(self.template, user=user, order_round=self.current_order_round) send_mail(subject=subject, message=plain_message, from_email="VOKO Utrecht <*****@*****.**>", recipient_list=["%s <%s>" % (user.get_full_name(), user.email)], html_message=html_message) log_event(operator=self.request.user, user=user, event="Mail verstuurd met onderwerp '%s'" % subject, extra=html_message)
def enable_user(modeladmin, request, queryset): for user in queryset: if not user.email_confirmation.is_confirmed or user.is_active: return queryset.update(can_activate=True) for user in queryset: ## send mail mail_template = get_template_by_id(ACTIVATE_ACCOUNT_MAILTEMPLATE_ID) subject, html_message, plain_message = render_mail_template(mail_template, user=user) send_mail(subject=subject, message=plain_message, from_email="VOKO Utrecht <*****@*****.**>", recipient_list=["%s <%s>" % (user.get_full_name(), user.email)], html_message=html_message) log.log_event(user=user, event="User set to 'can_activate=True' and activation mail sent", extra=html_message)
def enable_user(modeladmin, request, queryset): for user in queryset: if not user.email_confirmation.is_confirmed or user.is_active: return queryset.update(can_activate=True) for user in queryset: # send mail mail_template = get_template_by_id(config.ACTIVATE_ACCOUNT_MAIL) (subject, html_message, plain_message, from_email) = render_mail_template(mail_template, user=user) mail_user(user, subject, html_message, plain_message, from_email) log.log_event( user=user, event="User set to 'can_activate=True' and activation mail sent", extra=html_message)
def determine_if_product_is_new_and_set_label(self): """ Set new=True on product when similar product cannot be found in previous order round. 'new' attribute is used to show 'New' label in product list. """ try: prev_round = OrderRound.objects.get(id=self.order_round.id-1) except OrderRound.DoesNotExist: return if not prev_round.products.filter(name=self.name, supplier=self.supplier, unit=self.unit): self.new = True self.save() log_event(event="Setting product %s to 'new' because I could not find a " "similar product in order round %d" % (self, prev_round.id))
def determine_if_product_is_new_and_set_label(self): """ Set new=True on product when similar product cannot be found in previous order round. 'new' attribute is used to show 'New' label in product list. """ try: prev_round = OrderRound.objects.get(id=self.order_round.id - 1) except OrderRound.DoesNotExist: return if not prev_round.products.filter( name=self.name, supplier=self.supplier, unit=self.unit): self.new = True self.save() log_event( event="Setting product %s to 'new' because I could not find a " "similar product in order round %d" % (self, prev_round.id))
def get(self, request, *args, **kwargs): order_to_pay = get_order_to_pay(request.user) if not order_to_pay: messages.error(request, "Geen bestelling gevonden") return redirect(reverse('view_products')) # Sanity checks assert order_to_pay.finalized is True assert order_to_pay.paid is False order_to_pay.finalized = False order_to_pay.save() log_event(event="Payment for order %s canceled" % order_to_pay.id, user=order_to_pay.user) return HttpResponseRedirect( reverse("finish_order", args=(order_to_pay.pk, )))
def get(self, request, *args, **kwargs): order_to_pay = get_order_to_pay(request.user) if not order_to_pay: messages.error(request, "Geen bestelling gevonden") return redirect(reverse('view_products')) # Sanity checks assert order_to_pay.finalized is True assert order_to_pay.paid is False order_to_pay.finalized = False order_to_pay.save() log_event(event="Payment for order %s canceled" % order_to_pay.id, user=order_to_pay.user) return HttpResponseRedirect( reverse("finish_order", args=(order_to_pay.pk,)))
def send_reminder_mails(self): if self.reminder_sent is True: log_event(event="Not sending order reminder for round %d because " "reminder_sent is True" % self.pk) return log_event(event="Sending order reminder for round %d" % self.pk) mail_template = get_template_by_id(config.ORDER_REMINDER_MAIL) self.reminder_sent = True self.save() for user in self.get_users_without_orders(): rendered_template_vars = render_mail_template( mail_template, user=user, order_round=self) mail_user(user, *rendered_template_vars)
def _send_mails(self): for user in self.users: ( subject, html_message, plain_message, from_email ) = render_mail_template( self.template, user=user, order_round=self.current_order_round ) mail_user(user, subject, html_message, plain_message, from_email) log_event(operator=self.request.user, user=user, event="Mail verstuurd met onderwerp '%s'" % subject, extra=html_message)
def send_reminder_mails(self): if self.reminder_sent is True: log_event(event="Not sending order reminder for round %d because " "reminder_sent is True" % self.pk) return log_event(event="Sending order reminder for round %d" % self.pk) mail_template = get_template_by_id(config.ORDER_REMINDER_MAIL) self.reminder_sent = True self.save() for user in self.get_users_without_orders(): rendered_template_vars = render_mail_template(mail_template, user=user, order_round=self) mail_user(user, *rendered_template_vars)
def save(self, commit=True): with transaction.atomic(): # Create user user = super(VokoUserFinishForm, self).save(commit=False) user.set_password(self.cleaned_data["password1"]) user.is_active = True user.activated = datetime.now(UTC) if commit: user.save() UserProfile.objects.create( user=user, notes=self.cleaned_data['notes'], phone_number=self.cleaned_data['phone_number']) self._notify_admins_about_activated_user(user) log.log_event(user=user, event="User finished registration") return user
def save(self, commit=True): with transaction.atomic(): # Save zip code in address address = Address.objects.create(zip_code=self.cleaned_data['zip_code']) # Create user user = super(VokoUserFinishForm, self).save(commit=False) user.set_password(self.cleaned_data["password1"]) user.is_active = True if commit: user.save() # Lastly, link the two UserProfile.objects.create(user=user, address=address, notes=self.cleaned_data['notes'], phone_number=self.cleaned_data['phone_number']) self._notify_admins_about_activated_user(user) log.log_event(user=user, event="User finished registration") return user
def send_distribution_mails(self): if self.distribution_mails_sent is True: log_event(event="Not sending distribution mails for round %d " "because distribution_mails_sent is True" % self.pk) return log_event(event="Sending distribution mails for round %d" % self.pk) mail_template = get_template_by_id(config.DISTRIBUTION_MAIL) self.distribution_mails_sent = True self.save() shifts = self.distribution_shifts.all() for shift in shifts: for user in shift.members.all(): rendered_template_vars = render_mail_template( mail_template, user=user, shift=shift, base_url=settings.BASE_URL) mail_user(user, *rendered_template_vars)
def get_context_data(self, **kwargs): context = super(ConfirmTransactionView, self).get_context_data( **kwargs) order_id = self.request.GET.get('order') # Payment may already be confirmed by the webhook try: order = Order.objects.get(id=order_id, user=self.request.user) except Order.DoesNotExist: raise Http404 if order.paid is True: context['payment_succeeded'] = True return context payment = Payment.objects.filter(order__id=order_id, succeeded=False,)\ .order_by('id').last() if payment is None: raise Http404 mollie_payment = self.get_payment(payment.mollie_id) success = mollie_payment.isPaid() if success: if (payment.order.finalized is True and payment.order.paid is False and payment.order.order_round.is_open is True): payment.succeeded = True payment.save() payment.create_and_link_credit() payment.order.complete_after_payment() log_event( event="Payment %s for order %s and amount %f succeeded" % (payment.id, payment.order.id, payment.amount), user=payment.order.user) else: log_event(event="Payment %s was already paid" % payment.id, user=payment.order.user) try: del self.request.session['order_to_pay'] except KeyError: pass else: log_event(event="Payment %s for order %s and amount %f failed" % (payment.id, payment.order.id, payment.amount), user=payment.order.user) context['payment_succeeded'] = success return context
def post(self, request, *args, **kwargs): order = self.get_object() user_notes = request.POST.get('notes').strip() if user_notes: order.user_notes = user_notes log_event(event="Finalizing order %s" % order.id, user=order.user) order.finalized = True # Freeze order order.save() if self.calculate_payment() == 0: log_event(event="Payment for order %d not necessary because order total is %f and user's credit is %f" % (order.id, order.total_price, order.user.balance.credit()), user=order.user) messages.add_message(self.request, messages.SUCCESS, 'Omdat je genoeg krediet had was betalen niet nodig. ' 'Je bestelling is bevestigd.') order.complete_after_payment() return redirect(reverse('order_summary', args=(order.pk,))) # Store order_id in session request.session['order_to_pay'] = order.id return redirect('finance.choosebank')
def send_prepare_ride_mails(self): if self.prepare_ride_mails_sent is True: log_event(event="Not sending prepare ride mails for round %d " "because prepare_ride_mails_sent is True" % self.pk) return log_event(event="Sending prepare ride mails for round %d" % self.pk) mail_template = get_template_by_id(config.PREPARE_RIDE_MAIL) self.prepare_ride_mails_sent = True self.save() rides = self.rides.all() for ride in rides: drivers = [ride.driver, ride.codriver] for user in drivers: rendered_template_vars = render_mail_template( mail_template, user=user, ride=ride, base_url=settings.BASE_URL) mail_user(user, *rendered_template_vars)
def save(self, commit=True): with transaction.atomic(): # Update user user = super(ChangeProfileForm, self).save() if self.cleaned_data['password1']: user.set_password(self.cleaned_data["password1"]) # Profile userprofile = user.userprofile userprofile.phone_number = self.cleaned_data['phone_number'] # And address address = user.userprofile.address address.zip_code = self.cleaned_data['zip_code'] if commit: user.save() userprofile.save() address.save() log.log_event(user=user, event="User changed profile") return user
def enable_user(modeladmin, request, queryset): for user in queryset: if not user.email_confirmation.is_confirmed or user.is_active: return queryset.update(can_activate=True) for user in queryset: # send mail mail_template = get_template_by_id(config.ACTIVATE_ACCOUNT_MAIL) ( subject, html_message, plain_message, from_email ) = render_mail_template( mail_template, user=user ) mail_user(user, subject, html_message, plain_message, from_email) log.log_event( user=user, event="User set to 'can_activate=True' and activation mail sent", extra=html_message )
def post(self, request, *args, **kwargs): mollie_id = request.POST.get('id') payment = get_object_or_404(Payment, mollie_id=mollie_id) mollie_payment = self.get_payment(payment.mollie_id) success = mollie_payment.isPaid() if not success: log_event( event="Payment %s for order %s and amount %f " "failed via callback" % (payment.id, payment.order.id, payment.amount), user=payment.order.user) return HttpResponse("") # Successful payment! payment.succeeded = True payment.save() payment.create_and_link_credit() log_event( event="Payment %s for order %s and amount %f " "succeeded via callback" % (payment.id, payment.order.id, payment.amount), user=payment.order.user) if payment.order.paid is False: # Order has not been paid, but the payment has now been confirmed # and credit has been created. # Time to finish the order, if the order round is still open. # Sanity Check assert payment.order.finalized is True if payment.order.order_round.is_open: payment.order.complete_after_payment() else: # Corner case where payment was executed before closing time, # but never finished (user closed browser tab), # the payment is now validated by callback, but order round is # closed and our suppliers likely have been mailed the totals. # Credit for the user has just been created, but we don't # want to complete the order because it was placed too late. log_event( event="Order round %s is closed, so not finishing " "order %s via callback!" % ( payment.order.order_round.id, payment.order.id), user=payment.order.user) payment.order.mail_failure_notification() return HttpResponse("")
def get_context_data(self, **kwargs): context = super(ConfirmTransactionView, self).get_context_data(**kwargs) order_id = self.request.GET.get('order') # Payment may already be confirmed by the webhook try: order = Order.objects.get(id=order_id, user=self.request.user) except Order.DoesNotExist: raise Http404 if order.paid is True: context['payment_succeeded'] = True return context payment = Payment.objects.filter(order__id=order_id, succeeded=False,)\ .order_by('id').last() if payment is None: raise Http404 mollie_payment = self.get_payment(payment.mollie_id) success = mollie_payment.isPaid() if success: if (payment.order.finalized is True and payment.order.paid is False and payment.order.order_round.is_open is True): payment.succeeded = True payment.save() payment.create_and_link_credit() payment.order.complete_after_payment() log_event( event="Payment %s for order %s and amount %f succeeded" % (payment.id, payment.order.id, payment.amount), user=payment.order.user) else: log_event(event="Payment %s was already paid" % payment.id, user=payment.order.user) else: log_event(event="Payment %s for order %s and amount %f failed" % (payment.id, payment.order.id, payment.amount), user=payment.order.user) context['payment_succeeded'] = success return context
def post(self, request, *args, **kwargs): mollie_id = request.POST.get('id') payment = get_object_or_404(Payment, mollie_id=mollie_id) mollie_payment = self.get_payment(payment.mollie_id) success = mollie_payment.isPaid() if not success: log_event(event="Payment %s for order %s and amount %f " "failed via callback" % (payment.id, payment.order.id, payment.amount), user=payment.order.user) return HttpResponse("") # Successful payment! payment.succeeded = True payment.save() payment.create_and_link_credit() log_event(event="Payment %s for order %s and amount %f " "succeeded via callback" % (payment.id, payment.order.id, payment.amount), user=payment.order.user) if payment.order.paid is False: # Order has not been paid, but the payment has now been confirmed # and credit has been created. # Time to finish the order, if the order round is still open. # Sanity Check assert payment.order.finalized is True if payment.order.order_round.is_open: payment.order.complete_after_payment() else: # Corner case where payment was executed before closing time, # but never finished (user closed browser tab), # the payment is now validated by callback, but order round is # closed and our suppliers likely have been mailed the totals. # Credit for the user has just been created, but we don't # want to complete the order because it was placed too late. log_event(event="Order round %s is closed, so not finishing " "order %s via callback!" % (payment.order.order_round.id, payment.order.id), user=payment.order.user) payment.order.mail_failure_notification() return HttpResponse("")
def do(self): order_round = get_current_order_round() print(("Order round: %s" % order_round)) if order_round.is_open: print("Order round is closed") return if order_round.is_not_open_yet(): print("Order round is not open yet") return if order_round.order_placed: print("Order has already been placed") return # To prevent mail loops order_round.order_placed = True order_round.save() for supplier in Supplier.objects.all(): if not supplier.has_orders_in_current_order_round(): print(("No orders for supplier %s" % supplier)) log_event(event="Supplier %s has no orders in current round, " "so not sending order list." % supplier) continue print(("Generating lists for supplier %s" % supplier)) # Generate CSV in_mem_file = io.BytesIO() csv_writer = csv.writer(in_mem_file, delimiter=';', quotechar='|') # Write header row csv_writer.writerow( ["Aantal", "Eenheid", "Product", "Omschrijving", "Inkoopprijs Euro", "Subtotaal"]) ordered_products = supplier.products. \ exclude(orderproducts=None). \ filter(orderproducts__order__paid=True). \ filter(order_round=order_round). \ annotate(amount_sum=Sum('orderproducts__amount')) if not ordered_products: log_event(event="Supplier %s has only STOCK orders " "in current round, " "so not sending order list." % supplier) continue # Write products and amounts for obj in ordered_products: csv_writer.writerow([ fix_decimal_separator(obj.amount_sum), obj.unit_of_measurement, obj.name, obj.description.replace("\n", " ").replace("\r", " "), # TODO make sure newlines aren't stored # in our products fix_decimal_separator(obj.base_price), fix_decimal_separator(obj.amount_sum * obj.base_price) ]) # Write 'total' row total = fix_decimal_separator(sum( [obj.amount_sum * obj.base_price for obj in ordered_products])) csv_writer.writerow([]) csv_writer.writerow(["TOTAAL", "", "", "", "", total]) in_mem_file.seek(0) in_mem_file.seek(0) # Why is this here twice? # Generate mail subject = ('VOKO Utrecht - Bestellijst voor %s' % order_round.collect_datetime.strftime("%d %B %Y")) from_email = 'VOKO Utrecht Boerencontact <*****@*****.**>' to = '%s <%s>' % (supplier.name, supplier.email) text_content = """ Hoi %s, Hierbij sturen we onze bestelling voor bestelronde %d voor ons uitlevermoment op %s. De bestelling is in CSV-formaat, dit is te openen in bijvoorbeeld Excel. Dit is een geautomatiseerd bericht, maar reageren is gewoon mogelijk. Vriendelijke groeten, VOKO Utrecht """ % ( supplier, order_round.pk, order_round.collect_datetime.strftime("%d %B %Y") ) msg = EmailMultiAlternatives( subject, text_content, from_email, [to], cc=["VOKO Utrecht Boerencontact <*****@*****.**>"] ) msg.attach('voko_utrecht_bestelling_ronde_%d.csv' % order_round.pk, in_mem_file.read().decode("utf-8"), 'text/csv') msg.send()
def do(self): order_round = get_current_order_round() print(("Order round: %s" % order_round)) if order_round.is_open: print("Order round is closed") return if order_round.is_not_open_yet(): print("Order round is not open yet") return if order_round.order_placed: print("Order has already been placed") return # To prevent mail loops order_round.order_placed = True order_round.save() for supplier in Supplier.objects.all(): if not supplier.has_orders_in_current_order_round(): print(("No orders for supplier %s" % supplier)) log_event(event="Supplier %s has no orders in current round, " "so not sending order list." % supplier) continue print(("Generating lists for supplier %s" % supplier)) # Generate CSV in_mem_file = io.BytesIO() csv_writer = csv.writer(in_mem_file, delimiter=';', quotechar='|') # Write header row csv_writer.writerow([ "Aantal", "Eenheid", "Product", "Omschrijving", "Inkoopprijs Euro", "Subtotaal" ]) ordered_products = supplier.products. \ exclude(orderproducts=None). \ filter(orderproducts__order__paid=True). \ filter(order_round=order_round). \ annotate(amount_sum=Sum('orderproducts__amount')) if not ordered_products: log_event(event="Supplier %s has only STOCK orders " "in current round, " "so not sending order list." % supplier) continue # Write products and amounts for obj in ordered_products: csv_writer.writerow([ fix_decimal_separator(obj.amount_sum), obj.unit_of_measurement, obj.name, obj.description.replace("\n", " ").replace("\r", " "), # TODO make sure newlines aren't stored # in our products fix_decimal_separator(obj.base_price), fix_decimal_separator(obj.amount_sum * obj.base_price) ]) # Write 'total' row total = fix_decimal_separator( sum([ obj.amount_sum * obj.base_price for obj in ordered_products ])) csv_writer.writerow([]) csv_writer.writerow(["TOTAAL", "", "", "", "", total]) in_mem_file.seek(0) in_mem_file.seek(0) # Why is this here twice? # Generate mail subject = ('VOKO Utrecht - Bestellijst voor %s' % order_round.collect_datetime.strftime("%d %B %Y")) from_email = 'VOKO Utrecht Boerencontact <*****@*****.**>' to = '%s <%s>' % (supplier.name, supplier.email) text_content = """ Hoi %s, Hierbij sturen we onze bestelling voor bestelronde %d voor ons uitlevermoment op %s. De bestelling is in CSV-formaat, dit is te openen in bijvoorbeeld Excel. Dit is een geautomatiseerd bericht, maar reageren is gewoon mogelijk. Vriendelijke groeten, VOKO Utrecht """ % (supplier, order_round.pk, order_round.collect_datetime.strftime("%d %B %Y")) msg = EmailMultiAlternatives( subject, text_content, from_email, [to], cc=["VOKO Utrecht Boerencontact <*****@*****.**>"]) msg.attach('voko_utrecht_bestelling_ronde_%d.csv' % order_round.pk, in_mem_file.read().decode("utf-8"), 'text/csv') msg.send()