0.10.2 mail alert by new routes
This commit is contained in:
@@ -126,7 +126,7 @@ def send_message_ajax(request):
|
|||||||
return JsonResponse({'html': html}, status=400)
|
return JsonResponse({'html': html}, status=400)
|
||||||
|
|
||||||
Dict = {
|
Dict = {
|
||||||
'logo': f'{request.scheme}://{sets["domain"]}/static/img/svg/LogoMobile.svg',
|
'logo': f'{sets["domain"]}/static/img/svg/LogoMobile.svg',
|
||||||
'project_name': sets['project_name'],
|
'project_name': sets['project_name'],
|
||||||
'message_title': subject,
|
'message_title': subject,
|
||||||
'message_text': f'<p><b>{_("ДАННЫЕ ЗАПРОСА")}</b></p>'
|
'message_text': f'<p><b>{_("ДАННЫЕ ЗАПРОСА")}</b></p>'
|
||||||
|
|||||||
@@ -10,8 +10,15 @@ def get_options_by_opt_types(opt_types, only_vals=False):
|
|||||||
|
|
||||||
opts = Option.objects.filter(**kwargs)
|
opts = Option.objects.filter(**kwargs)
|
||||||
if opts and only_vals:
|
if opts and only_vals:
|
||||||
opts = opts.values('opt_type', 'value')
|
res = {}
|
||||||
opts = {item['opt_type']: item['value'] for item in opts}
|
opts = opts.values('opt_type', 'value', 'prefix')
|
||||||
|
for item in opts:
|
||||||
|
if item['prefix']:
|
||||||
|
res.update({item['opt_type']: f"{item['prefix']}{item['value']}"})
|
||||||
|
else:
|
||||||
|
res.update({item['opt_type']: f"{item['value']}"})
|
||||||
|
return res
|
||||||
|
|
||||||
return opts
|
return opts
|
||||||
|
|
||||||
def get_first_option_value_by_opt_type(opt_type):
|
def get_first_option_value_by_opt_type(opt_type):
|
||||||
|
|||||||
@@ -19,18 +19,21 @@ def test_code(request):
|
|||||||
from RoutesApp.models import Route
|
from RoutesApp.models import Route
|
||||||
from ReferenceDataApp.models import Airport, City
|
from ReferenceDataApp.models import Airport, City
|
||||||
|
|
||||||
try:
|
from RoutesApp.search_matches import search_matches
|
||||||
# body = request.body
|
search_matches()
|
||||||
# data = json.loads(body)
|
|
||||||
# if 'head' not in data or 'body' not in data or 'id' not in data:
|
# try:
|
||||||
# return JsonResponse(status=400, data={"message": "Invalid data format"})
|
# # body = request.body
|
||||||
# user_id = data['id']
|
# # data = json.loads(body)
|
||||||
user = request.user
|
# # if 'head' not in data or 'body' not in data or 'id' not in data:
|
||||||
payload = {'head': '123', 'body': 'qwerty'}
|
# # return JsonResponse(status=400, data={"message": "Invalid data format"})
|
||||||
send_user_notification(user=user, payload=payload, ttl=1000)
|
# # user_id = data['id']
|
||||||
return JsonResponse(status=200, data={"message": "Web push successful"})
|
# user = request.user
|
||||||
except TypeError:
|
# payload = {'head': '123', 'body': 'qwerty'}
|
||||||
return JsonResponse(status=500, data={"message": "An error occurred"})
|
# send_user_notification(user=user, payload=payload, ttl=1000)
|
||||||
|
# return JsonResponse(status=200, data={"message": "Web push successful"})
|
||||||
|
# except TypeError:
|
||||||
|
# return JsonResponse(status=500, data={"message": "An error occurred"})
|
||||||
|
|
||||||
# routes = Route.objects.all()
|
# routes = Route.objects.all()
|
||||||
#
|
#
|
||||||
@@ -49,7 +52,7 @@ def test_code(request):
|
|||||||
# if required_save:
|
# if required_save:
|
||||||
# route.save()
|
# route.save()
|
||||||
|
|
||||||
# return HttpResponse('finished')
|
return HttpResponse('finished')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from django.contrib import admin
|
|||||||
|
|
||||||
class Admin_Route(Admin_Trans_BaseModel):
|
class Admin_Route(Admin_Trans_BaseModel):
|
||||||
list_display = [
|
list_display = [
|
||||||
'id', 'owner_type', 'type_transport', 'cargo_type',
|
'id', 'owner_type', 'receive_msg_by_email', 'type_transport', 'cargo_type',
|
||||||
'departure_DT', 'from_city', 'from_place',
|
'departure_DT', 'from_city', 'from_place',
|
||||||
'arrival_DT', 'to_city', 'to_place', 'owner',
|
'arrival_DT', 'to_city', 'to_place', 'owner',
|
||||||
'order', 'modifiedDT', 'createDT'
|
'order', 'modifiedDT', 'createDT'
|
||||||
@@ -14,5 +14,6 @@ class Admin_Route(Admin_Trans_BaseModel):
|
|||||||
|
|
||||||
list_filter = ['owner_type', 'type_transport', 'cargo_type', 'from_place', 'arrival_DT', 'modifiedDT', 'createDT']
|
list_filter = ['owner_type', 'type_transport', 'cargo_type', 'from_place', 'arrival_DT', 'modifiedDT', 'createDT']
|
||||||
search_fields = ['owner__first_name', 'owner__last_name']
|
search_fields = ['owner__first_name', 'owner__last_name']
|
||||||
|
raw_id_fields = ['from_city', 'to_city']
|
||||||
|
|
||||||
admin.site.register(Route,Admin_Route)
|
admin.site.register(Route,Admin_Route)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class RouteForm(forms.ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
if 'phone' in cleaned_data and 'phone' in cleaned_data:
|
if 'phone' in cleaned_data and 'phone' in cleaned_data:
|
||||||
from BaseModels.validators.form_field_validators import get_phone_valid_error
|
from BaseModels.validators.form_field_validators import get_phone_valid_error
|
||||||
error = get_phone_valid_error(cleaned_data["phone"])
|
error = get_phone_valid_error(cleaned_data["phone"])
|
||||||
|
|||||||
@@ -154,10 +154,13 @@ def get_routes_Dict(user=None, data=None):
|
|||||||
if val:
|
if val:
|
||||||
if key == 'weight':
|
if key == 'weight':
|
||||||
weight_list = val.split(';')
|
weight_list = val.split(';')
|
||||||
if weight_list[0]:
|
if len(weight_list) > 1:
|
||||||
kwargs.update({f'{key}__gte': int(weight_list[0])})
|
if weight_list[0]:
|
||||||
if weight_list[1]:
|
kwargs.update({f'{key}__gte': int(weight_list[0])})
|
||||||
kwargs.update({f'{key}__lte': int(weight_list[1])})
|
if weight_list[1]:
|
||||||
|
kwargs.update({f'{key}__lte': int(weight_list[1])})
|
||||||
|
else:
|
||||||
|
kwargs.update({f'{key}__lte': int(weight_list[0])})
|
||||||
|
|
||||||
if key == 'type_transport':
|
if key == 'type_transport':
|
||||||
items_list = val.split(',')
|
items_list = val.split(',')
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ def create_or_change_route_ajax(request, route_id=None):
|
|||||||
return JsonResponse({'html': html}, status=400)
|
return JsonResponse({'html': html}, status=400)
|
||||||
|
|
||||||
obj = form.save(commit=False)
|
obj = form.save(commit=False)
|
||||||
if 'owner_type' in data:
|
if 'owner_type' in data and data['owner_type']:
|
||||||
obj.owner_type = data['owner_type']
|
obj.owner_type = data['owner_type']
|
||||||
|
|
||||||
if obj.from_address_point:
|
if obj.from_address_point:
|
||||||
|
|||||||
0
RoutesApp/management/__init__.py
Normal file
0
RoutesApp/management/__init__.py
Normal file
0
RoutesApp/management/commands/__init__.py
Normal file
0
RoutesApp/management/commands/__init__.py
Normal file
36
RoutesApp/management/commands/every_1hour_start.py
Normal file
36
RoutesApp/management/commands/every_1hour_start.py
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from datetime import datetime
|
||||||
|
from BaseModels.mailSender import techSendMail
|
||||||
|
from GeneralApp.funcs_options import get_options_by_opt_types, get_mail_send_options
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
mail_sets = get_mail_send_options()
|
||||||
|
|
||||||
|
log = ''
|
||||||
|
log_begin_DT = datetime.now()
|
||||||
|
msg = str(log_begin_DT)
|
||||||
|
print('-------------')
|
||||||
|
print(msg)
|
||||||
|
|
||||||
|
try:
|
||||||
|
from ...search_matches import search_matches
|
||||||
|
msg = search_matches()
|
||||||
|
if msg:
|
||||||
|
print(msg)
|
||||||
|
except Exception as e:
|
||||||
|
msg = f'every_1hour_start search_matches fail = {str(e)}'
|
||||||
|
print(msg)
|
||||||
|
techSendMail(mail_sets, msg, title='every_1hour_start search_matches')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if msg:
|
||||||
|
techSendMail(mail_sets, str(msg), title='every_1hour_start get_competitors_prices')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
print(f'- processing time = {str(datetime.now() - log_begin_DT)} -')
|
||||||
|
|
||||||
|
|
||||||
13
RoutesApp/management/commands/fix_code.py
Normal file
13
RoutesApp/management/commands/fix_code.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
|
||||||
|
# from B2BApp.funcs import assign_contracts_for_orders_by_tmp_data
|
||||||
|
# log = assign_contracts_for_orders_by_tmp_data()
|
||||||
|
from GeneralApp.views import test_code
|
||||||
|
test_code(None)
|
||||||
|
|
||||||
|
self.stdout.write(u'fix_code end')
|
||||||
101
RoutesApp/search_matches.py
Normal file
101
RoutesApp/search_matches.py
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
from .models import *
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from django.utils.translation import gettext as _
|
||||||
|
from django.template.loader import render_to_string
|
||||||
|
from GeneralApp.funcs_options import get_options_by_opt_types, get_mail_send_options
|
||||||
|
from BaseModels.mailSender import admin_send_mail_by_SMTPlib, techSendMail
|
||||||
|
|
||||||
|
def send_mail_found_matches_routes(route, kwargs, search_owner_type):
|
||||||
|
|
||||||
|
Dict = {
|
||||||
|
'route': route,
|
||||||
|
'search_owner_type': search_owner_type
|
||||||
|
}
|
||||||
|
sets = get_options_by_opt_types(['domain', 'project_name'], only_vals=True)
|
||||||
|
Dict.update(sets)
|
||||||
|
Dict.update({'logo': f'{sets["domain"]}/static/img/svg/LogoMobile.svg',})
|
||||||
|
|
||||||
|
find_routes_page_url = f'{sets["domain"]}/routes/route_search_results/?'
|
||||||
|
kwargs_list = [f'{key}={value}' for key, value in kwargs.items()]
|
||||||
|
kwargs_list.append(f'owner_type={search_owner_type}')
|
||||||
|
find_routes_page_url += f'{"&".join(kwargs_list)}'
|
||||||
|
Dict.update({'find_routes_page_url': find_routes_page_url})
|
||||||
|
|
||||||
|
html = render_to_string('mail/m_found_matched_routes.html', Dict)
|
||||||
|
|
||||||
|
|
||||||
|
mail_sets = get_mail_send_options()
|
||||||
|
to = [route.owner.email, 'web@syncsystems.net']
|
||||||
|
subject = _('Мы нашли исполнителя по Вашему объявлению!')
|
||||||
|
res = admin_send_mail_by_SMTPlib(
|
||||||
|
mail_sets,
|
||||||
|
subject=subject,
|
||||||
|
from_email=mail_sets['sender_email'], to=to,
|
||||||
|
html_content=html
|
||||||
|
)
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def search_matches(for_routes=None):
|
||||||
|
|
||||||
|
log = ''
|
||||||
|
|
||||||
|
try:
|
||||||
|
if not for_routes:
|
||||||
|
for_routes = Route.objects.filter(
|
||||||
|
createDT__gte=datetime.now() - timedelta(hours=1),
|
||||||
|
receive_msg_by_email=True
|
||||||
|
)
|
||||||
|
|
||||||
|
check_fields = [
|
||||||
|
'type_transport', 'departure_DT', 'arrival_DT', 'from_address_point', 'to_address_point',
|
||||||
|
'from_place', 'to_place', 'cargo_type', 'weight'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
for route in for_routes:
|
||||||
|
kwargs = {}
|
||||||
|
params = {}
|
||||||
|
|
||||||
|
for field_name in check_fields:
|
||||||
|
field_val = getattr(route, field_name, None)
|
||||||
|
if field_val:
|
||||||
|
if type(field_val) == datetime:
|
||||||
|
params.update({f"{field_name}": f'{field_val.strftime("%d.%m.%Y")} - {field_val.strftime("%d.%m.%Y")}'})
|
||||||
|
kwargs.update({f"{field_name}__date": field_val.date()})
|
||||||
|
elif field_name == 'weight':
|
||||||
|
# print(field_name)
|
||||||
|
params.update({f"{field_name}": field_val})
|
||||||
|
if route.owner_type == 'mover':
|
||||||
|
kwargs.update({f"{field_name}__lte": field_val})
|
||||||
|
else:
|
||||||
|
kwargs.update({f"{field_name}__gte": field_val})
|
||||||
|
else:
|
||||||
|
kwargs.update({field_name: field_val})
|
||||||
|
params.update({field_name: field_val})
|
||||||
|
|
||||||
|
found_routes = Route.objects.exclude(
|
||||||
|
id=route.id,
|
||||||
|
).exclude(
|
||||||
|
owner=route.owner
|
||||||
|
).exclude(
|
||||||
|
owner_type=route.owner_type
|
||||||
|
).filter(
|
||||||
|
**kwargs
|
||||||
|
# ).count(
|
||||||
|
)
|
||||||
|
|
||||||
|
if found_routes:
|
||||||
|
msg = send_mail_found_matches_routes(route, params, found_routes[0].owner_type)
|
||||||
|
if msg:
|
||||||
|
log += msg
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
msg = f'<br>\n! search_matches Error = {str(e)}'
|
||||||
|
log += msg
|
||||||
|
|
||||||
|
mail_sets = get_mail_send_options()
|
||||||
|
techSendMail(mail_sets, log, msg)
|
||||||
|
|
||||||
|
return log
|
||||||
80
templates/mail/m_found_matched_routes.html
Normal file
80
templates/mail/m_found_matched_routes.html
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
|
||||||
|
<div style="font-family:Calibri,Candara,Segoe,'Segoe UI',Optima,Arial,sans-serif;
|
||||||
|
padding:10px; background-color: #F8F8F8;"
|
||||||
|
>
|
||||||
|
<div style="line-height:1.0em; width: 660px">
|
||||||
|
<div style="padding:5px; text-align: center;">
|
||||||
|
<img src="{{ logo }}" alt="{{ project_name }}" style="margin:0;padding:0;">
|
||||||
|
</div>
|
||||||
|
<p style="font-weight:700; font-size:25px; text-align:center;
|
||||||
|
padding:0; line-height:1em; text-transform: uppercase; color: #ff613a;
|
||||||
|
margin: auto; max-width: 90%;
|
||||||
|
">
|
||||||
|
Здравствуйте, {{ route.owner }}!
|
||||||
|
</p>
|
||||||
|
<div style="line-height:1.0em; font-size:18px; margin: 5px 30px;
|
||||||
|
box-shadow: -1px 4px 10px 0 rgba(198, 199, 203, 0.20), 0 -1px 10px 0 rgba(198, 199, 203, 0.20);
|
||||||
|
padding: 30px; border-radius: 10px; background-color: #FFF;">
|
||||||
|
<p>Ранее вы на сайте <a href="{{ domain }}/profile/page/my_routes/"> размещали объявление о поиске {% if search_owner_type == 'mover' %}Перевозчика{% else %}Отправителя{% endif %}</a> и попросили нас уведомить Вас о появлении объявлений, которые соответствуют Вашему критерию.</p>
|
||||||
|
<p><b>Хорошая новость!</b></p>
|
||||||
|
<p><b>По заданным критериям поиска мы нашли исполнителя!</b></p>
|
||||||
|
<p>Чтобы узнать подробности и открыть доступ к контактам, перейдите <a href="{{ find_routes_page_url }}">по этой ссылке и используйте свои учетные данные для входа</a>.
|
||||||
|
<p>Если у вас возникнут вопросы или вам потребуется помощь, наша служба поддержки всегда готова помочь. Свяжитесь с нами по адресу <a href="mailto:support@tripwb.com">support@tripwb.com</a></p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Спасибо за то, что вы с нами!<br>
|
||||||
|
С уважением,<br>
|
||||||
|
Команда Trip With Bonus.<br>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% for button in message_buttons %}
|
||||||
|
<div style="text-align:center;font-weight: 700;">
|
||||||
|
<a href="{{ button.url }}">
|
||||||
|
<div style="display:inline-block;text-align:center;font-size:18px;padding:5px 10px;margin:5px;border-radius:2px;background-color:#61aeb6;color:#fff;text-decoration:none;line-height:1.0em;cursor:pointer">
|
||||||
|
{{ button.caption }}
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
<div style="text-align:center;width: 660px;line-height:1.1em">
|
||||||
|
<div style="margin: 40px 10px 10px;">
|
||||||
|
<hr>
|
||||||
|
{# <nobr><b>Адрес кафе:</b> Минск, ул. Будславская, 2</nobr>#}
|
||||||
|
{# <br>#}
|
||||||
|
{# <nobr><b>График работы:</b> пн-вс 12:00 - 24:00</nobr>#}
|
||||||
|
{# <br>#}
|
||||||
|
{# <nobr><b>Телефоны кафе:</b> +375 44 77 321 77</nobr>#}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="text-align: center;margin-top:5px">
|
||||||
|
{# <a href="https://baldenini.by/event/dostavka-edy" style="text-decoration: none;">#}
|
||||||
|
{# <div style="color: #311A12;#}
|
||||||
|
{# padding: 10px;#}
|
||||||
|
{# margin: 5px 10px 0 10px;#}
|
||||||
|
{# border: 2px solid #311A12;#}
|
||||||
|
{# border-radius: 5px;#}
|
||||||
|
{# font-size: 20px;#}
|
||||||
|
{# display: inline-block;#}
|
||||||
|
{# font-weight: 700;#}
|
||||||
|
{# text-transform: uppercase;">О ДОСТАВКЕ#}
|
||||||
|
{# </div>#}
|
||||||
|
{# </a>#}
|
||||||
|
{# <a href="https://baldenini.by/page/baldenini-cafe-o-nas" style="text-decoration: none;">#}
|
||||||
|
{# <div style="color: #311A12;#}
|
||||||
|
{# padding: 10px;#}
|
||||||
|
{# margin: 5px 10px 0 10px;#}
|
||||||
|
{# border: 2px solid #311A12;#}
|
||||||
|
{# border-radius: 5px;#}
|
||||||
|
{# font-size: 20px;#}
|
||||||
|
{# display: inline-block;#}
|
||||||
|
{# font-weight: 700;#}
|
||||||
|
{# text-transform: uppercase;">О BALDENINI CAFE#}
|
||||||
|
{# </div>#}
|
||||||
|
{# </a>#}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
Reference in New Issue
Block a user