Browse Source

remove broken app for dials

devel
Dmitry Novikov 7 years ago
parent
commit
4429c8e81d
  1. 40
      abonapp/locale/ru/LC_MESSAGES/django.po
  2. 45
      abonapp/templates/abonapp/dial_log.html
  3. 10
      abonapp/templates/abonapp/editAbon.html
  4. 5
      abonapp/templates/abonapp/ext.htm
  5. 1
      abonapp/urls.py
  6. 55
      abonapp/views.py
  7. 0
      dialing_app/__init__.py
  8. 3
      dialing_app/admin.py
  9. 5
      dialing_app/apps.py
  10. 8
      dialing_app/forms.py
  11. 172
      dialing_app/locale/ru/LC_MESSAGES/django.po
  12. 81
      dialing_app/migrations/0001_initial.py
  13. 27
      dialing_app/migrations/0002_auto_20180808_1236.py
  14. 0
      dialing_app/migrations/__init__.py
  15. 109
      dialing_app/models.py
  16. 58
      dialing_app/templates/ext.html
  17. 37
      dialing_app/templates/inbox_sms.html
  18. 78
      dialing_app/templates/index.html
  19. 23
      dialing_app/templates/modal_send_sms.html
  20. 48
      dialing_app/templates/vmail.html
  21. 0
      dialing_app/templatetags/__init__.py
  22. 20
      dialing_app/templatetags/telephone_filters.py
  23. 3
      dialing_app/tests.py
  24. 15
      dialing_app/urls.py
  25. 221
      dialing_app/views.py
  26. 1
      djing/settings.py
  27. 1
      djing/urls.py
  28. 2
      docs/install.md
  29. 9
      templates/base.html

40
abonapp/locale/ru/LC_MESSAGES/django.po

@ -403,46 +403,6 @@ msgstr "Автор"
msgid "Debts not found"
msgstr "Нет должников"
#: templates/abonapp/dial_log.html:8
msgid "Play"
msgstr "Слушать"
#: templates/abonapp/dial_log.html:9
msgid "calldate"
msgstr "дата звонка"
#: templates/abonapp/dial_log.html:10
msgid "src"
msgstr "кто"
#: templates/abonapp/dial_log.html:11
msgid "dst"
msgstr "куда"
#: templates/abonapp/dial_log.html:12
msgid "duration"
msgstr "прод."
#: templates/abonapp/dial_log.html:13
msgid "start"
msgstr "начало"
#: templates/abonapp/dial_log.html:14
msgid "answer"
msgstr "ответ"
#: templates/abonapp/dial_log.html:15
msgid "end"
msgstr "конец"
#: templates/abonapp/dial_log.html:16
msgid "disposition"
msgstr "состояние"
#: templates/abonapp/dial_log.html:38
msgid "Calls was not found"
msgstr "Звонки не найдены"
#: templates/abonapp/editAbon.html:10
msgid "Change subscriber"
msgstr "Изменение абонента"

45
abonapp/templates/abonapp/dial_log.html

@ -1,45 +0,0 @@
{% extends request.is_ajax|yesno:'nullcont.htm,abonapp/ext.htm' %}
{% load i18n %}
{% block content %}
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>{% trans 'Play' %}</th>
<th>{% trans 'calldate' %}</th>
<th>{% trans 'src' %}</th>
<th>{% trans 'dst' %}</th>
<th>{% trans 'duration' %}</th>
<th>{% trans 'start' %}</th>
<th>{% trans 'answer' %}</th>
<th>{% trans 'end' %}</th>
<th>{% trans 'disposition' %}</th>
</tr>
</thead>
<tbody>
{% for log in logs %}
<tr>
<td>
<audio preload="metadata" controls>
<source src="{{ log.url }}" type="audio/wav"/>
</audio>
</td>
<td>{{ log.calldate|date:'d E Y, H:i:s' }}</td>
<td>{{ log.src }}</td>
<td>{{ log.dst }}</td>
<td>{{ log.duration }}</td>
<td>{{ log.start|date:'d E Y, H:i:s' }}</td>
<td>{{ log.answer|date:'d E Y, H:i:s' }}</td>
<td>{{ log.end|date:'d E Y, H:i:s' }}</td>
<td>{{ log.locate_disposition }}</td>
</tr>
{% empty %}
<tr>
<td colspan="9">{% trans 'Calls was not found' %}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

10
abonapp/templates/abonapp/editAbon.html

@ -83,16 +83,6 @@
</a>
{% endif %}
{% if perms.dialing_app.add_smsout %}
<a href="{% url 'dialapp:send_sms' %}?path={{ request.path|urlencode }}&dst={{ form.telephone.value|urlencode }}" class="btn btn-default btn-modal">
<span class="glyphicon glyphicon-envelope"></span> {% trans 'Send sms' %}
</a>
{% else %}
<a href="#" class="btn btn-default disabled" title="{% trans 'Permission denied' %}">
<span class="glyphicon glyphicon-envelope"></span> {% trans 'Send sms' %}
</a>
{% endif %}
{% if perms.abonapp.view_passportinfo %}
<a href="{% url 'abonapp:passport_view' group.pk abon.username %}" class="btn btn-default btn-modal">
<span class="glyphicon glyphicon-paperclip"></span> {% trans 'Passport information' %}

5
abonapp/templates/abonapp/ext.htm

@ -39,11 +39,6 @@
<a href="{{ abtasklog }}">{% trans 'History of tasks' %}</a>
</li>
{% url 'abonapp:dials' group.pk abon.username as abdials %}
<li{% if abdials == request.path %} class="active"{% endif %}>
<a href="{{ abdials }}">{% trans 'Dialing' %}</a>
</li>
</ul>
<div class="tab-content">

1
abonapp/urls.py

@ -13,7 +13,6 @@ subscriber_patterns = [
path('addinvoice/', views.add_invoice, name='add_invoice'),
path('pick/', views.pick_tariff, name='pick_tariff'),
path('passport_view/', views.PassportUpdateView.as_view(), name='passport_view'),
path('dials/', views.DialsListView.as_view(), name='dials'),
# path('reset_ip/', views.reset_ip, name='reset_ip'),
path('unsubscribe_service/<int:abon_tariff_id>/', views.unsubscribe_service, name='unsubscribe_service'),
path('dev/', views.dev, name='dev'),

55
abonapp/views.py

@ -4,7 +4,6 @@ from typing import Dict, Optional
from abonapp.tasks import customer_nas_command, customer_nas_remove
from agent.commands.dhcp import dhcp_commit, dhcp_expiry, dhcp_release
from devapp.models import Device, Port as DevPort
from dialing_app.models import AsteriskCDR
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import login_required
@ -818,60 +817,6 @@ def vcards(r):
return response
class DialsListView(LoginRequiredMixin, OnlyAdminsMixin, OrderedFilteredList):
context_object_name = 'logs'
template_name = 'abonapp/dial_log.html'
def get_queryset(self):
abon = get_object_or_404(models.Abon,
username=self.kwargs.get('uname'))
if not self.request.user.has_perm('group_app.view_group', abon.group):
raise PermissionDenied
self.abon = abon
if abon.telephone is not None and abon.telephone != '':
tel = abon.telephone.replace('+', '')
additional_tels = tuple(
t.telephone for t in
models.AdditionalTelephone.objects.filter(
abon=abon
).iterator()
)
logs = AsteriskCDR.objects.filter(
Q(src__contains=tel) | Q(dst__contains=tel) |
Q(src__in=additional_tels) | Q(dst__in=additional_tels)
)
return logs
else:
return AsteriskCDR.objects.none()
def get_context_data(self, **kwargs):
context = super(DialsListView, self).get_context_data(**kwargs)
context['group'] = get_object_or_404(Group, pk=self.kwargs.get('gid'))
context['abon'] = self.abon
return context
def render_to_response(self, context, **response_kwargs):
if hasattr(self.abon.group, 'pk') and self.abon.group.pk != int(
self.kwargs.get('gid')):
return redirect(
'abonapp:dials', self.abon.group.pk,
self.abon.username
)
return super(DialsListView, self).render_to_response(
context,
**response_kwargs
)
def get(self, request, *args, **kwargs):
try:
return super(DialsListView, self).get(request, *args, **kwargs)
except ProgrammingError as e:
messages.error(request, e)
return redirect('abonapp:abon_home',
self.kwargs.get('gid'),
self.kwargs.get('uname'))
@login_required
@only_admins
@permission_required('abonapp.change_abon')

0
dialing_app/__init__.py

3
dialing_app/admin.py

@ -1,3 +0,0 @@
from django.contrib import admin
# Register your models here.

5
dialing_app/apps.py

@ -1,5 +0,0 @@
from django.apps import AppConfig
class DialingAppConfig(AppConfig):
name = 'dialing_app'

8
dialing_app/forms.py

@ -1,8 +0,0 @@
from django import forms
from .models import SMSOut
class SMSOutForm(forms.ModelForm):
class Meta:
model = SMSOut
fields = ('dst', 'text')

172
dialing_app/locale/ru/LC_MESSAGES/django.po

@ -1,172 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Dmitry Novikov nerosketch@gmail.com, 2017.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-08-09 14:59+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Dmitry Novikov nerosketch@gmail.com\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
"%100>=11 && n%100<=14)? 2 : 3);\n"
#: models.py:9 models.py:44
msgid "No answer"
msgstr "Не отвечен"
#: models.py:10 models.py:46 models.py:101
msgid "Failed"
msgstr "С ошибкой"
#: models.py:11 models.py:48
msgid "Busy"
msgstr "Занято"
#: models.py:12 models.py:50
msgid "Answered"
msgstr "Отвечен"
#: models.py:13 models.py:52
msgid "Unknown"
msgstr "Не определён"
#: models.py:86 models.py:87
msgid "SMS"
msgstr "СМС"
#: models.py:95
msgid "When"
msgstr "Когда"
#: models.py:96 templates/index.html:25
msgid "Telephone"
msgstr "Телефон"
#: models.py:97
msgid "Text"
msgstr "Текст"
#: models.py:99
msgid "New"
msgstr "Новое"
#: models.py:100
msgid "Sent"
msgstr "Отправленное"
#: models.py:103
msgid "Status"
msgstr "Статус"
#: models.py:111 models.py:112
msgid "Out SMS"
msgstr "Исходящие СМС"
#: templates/ext.html:8 templates/ext.html:25 views.py:45
msgid "Last calls"
msgstr "Последние звонки"
#: templates/ext.html:32 views.py:74
msgid "Voice mail request"
msgstr "Заявки на подключение"
#: templates/ext.html:39 views.py:83
msgid "Voice mail report"
msgstr "Заявки на поломки"
#: templates/ext.html:46 templates/inbox_sms.html:7
msgid "Inbox sms"
msgstr "Входящие смс"
#: templates/inbox_sms.html:23
msgid "Message history is empty"
msgstr "История сообщений пуста"
#: templates/inbox_sms.html:31 templates/modal_send_sms.html:5
msgid "Send sms"
msgstr "Отправить смс"
#: templates/index.html:9 templates/vmail.html:10
msgid "Play"
msgstr "Слушать"
#: templates/index.html:10 templates/index.html:36 templates/vmail.html:11
msgid "calldate"
msgstr "дата звонка"
#: templates/index.html:11 templates/vmail.html:12
msgid "src"
msgstr "кто"
#: templates/index.html:12
msgid "dst"
msgstr "куда"
#: templates/index.html:13 templates/vmail.html:13
msgid "duration"
msgstr "продолжительность"
#: templates/index.html:14 templates/vmail.html:14
msgid "start"
msgstr "начало"
#: templates/index.html:15 templates/vmail.html:15
msgid "answer"
msgstr "ответ"
#: templates/index.html:16 templates/vmail.html:16
msgid "end"
msgstr "конец"
#: templates/index.html:17 templates/vmail.html:17
msgid "disposition"
msgstr "состояние"
#: templates/index.html:23 views.py:94
msgid "Find dials"
msgstr "Найти звонки"
#: templates/index.html:34
msgid "Find by dates"
msgstr "Найти по дате"
#: templates/index.html:64
msgid "Download"
msgstr "Скачать"
#: templates/index.html:80 templates/vmail.html:42
msgid "Calls was not found"
msgstr "Звонки не найдены"
#: templates/modal_send_sms.html:19
msgid "Send"
msgstr "Отправить"
#: views.py:55
msgid "Multiple users with the telephone number"
msgstr "Несколько абонентов с указанным номером телефона"
#: views.py:57
msgid "User with the telephone number not found"
msgstr "Абонент с таким номером телефона не найден"
#: views.py:114
msgid "Make sure that your date format is correct"
msgstr "Убедитесь что формат времени корректен"
#: views.py:138
msgid "Message was enqueued for sending"
msgstr "Сообщение было поставлено в очередь для отправки"
#: views.py:151
msgid "fix form errors"
msgstr "Некоторые поля заполнены не правильно, проверте ещё раз"

81
dialing_app/migrations/0001_initial.py

@ -1,81 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-02-26 00:20
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='AsteriskCDR',
fields=[
('calldate', models.DateTimeField(default='0000-00-00 00:00:00', primary_key=True, serialize=False)),
('clid', models.CharField(default='', max_length=80)),
('src', models.CharField(default='', max_length=80)),
('dst', models.CharField(default='', max_length=80)),
('dcontext', models.CharField(default='', max_length=80)),
('channel', models.CharField(default='', max_length=80)),
('dstchannel', models.CharField(default='', max_length=80)),
('lastapp', models.CharField(default='', max_length=80)),
('lastdata', models.CharField(default='', max_length=80)),
('duration', models.IntegerField(default=0)),
('billsec', models.IntegerField(default=0)),
('start', models.DateTimeField(blank=True, default=None, null=True)),
('answer', models.DateTimeField(blank=True, default=None, null=True)),
('end', models.DateTimeField(blank=True, default=None, null=True)),
('disposition', models.CharField(
choices=[('NO ANSWER', 'No answer'), ('FAILED', 'Failed'), ('BUSY', 'Busy'),
('ANSWERED', 'Answered'), ('UNKNOWN', 'Unknown')], default='', max_length=45)),
('amaflags', models.IntegerField(default=0)),
('accountcode', models.CharField(default='', max_length=20)),
('userfield', models.CharField(default='', max_length=255)),
('uniqueid', models.CharField(default='', max_length=32)),
],
options={
'db_table': 'cdr',
'ordering': ['-calldate'],
'managed': False,
},
),
migrations.CreateModel(
name='SMSModel',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('when', models.DateTimeField(auto_now_add=True)),
('who', models.CharField(max_length=32)),
('dev', models.CharField(max_length=20)),
('text', models.CharField(max_length=255)),
],
options={
'verbose_name': 'SMS',
'verbose_name_plural': 'SMS',
'db_table': 'sms',
'ordering': ['-when'],
'permissions': (('can_view_sms', 'Can view sms'),),
},
),
migrations.CreateModel(
name='SMSOut',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('when', models.DateTimeField(auto_now_add=True, verbose_name='When')),
('dst', models.CharField(max_length=16, verbose_name='Telephone')),
('text', models.CharField(max_length=255, verbose_name='Text')),
('status',
models.CharField(choices=[('nw', 'New'), ('st', 'Sent'), ('fd', 'Failed')], default='nw', max_length=2,
verbose_name='Status')),
],
options={
'verbose_name': 'Out SMS',
'verbose_name_plural': 'Out SMS',
'db_table': 'out_sms',
'permissions': (('can_view_sms', 'Can view sms'), ('can_send_sms', 'Can send sms')),
},
),
]

27
dialing_app/migrations/0002_auto_20180808_1236.py

@ -1,27 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-08-08 12:36
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('dialing_app', '0001_initial'),
]
operations = [
migrations.AlterModelOptions(
name='asteriskcdr',
options={'managed': False, 'ordering': ('-calldate',)},
),
migrations.AlterModelOptions(
name='smsmodel',
options={'ordering': ('-when',), 'permissions': (('can_view_sms', 'Can view sms'),), 'verbose_name': 'SMS', 'verbose_name_plural': 'SMS'},
),
migrations.AlterModelOptions(
name='smsout',
options={'ordering': ('-when',), 'permissions': (('can_view_sms', 'Can view sms'), ('can_send_sms', 'Can send sms')), 'verbose_name': 'Out SMS', 'verbose_name_plural': 'Out SMS'},
),
]

0
dialing_app/migrations/__init__.py

109
dialing_app/models.py

@ -1,109 +0,0 @@
from django.db import models
from datetime import datetime
from django.utils.translation import gettext_lazy as _
from django.conf import settings
class AsteriskCDR(models.Model):
DISPOSITION_CHOICES = (
('NO ANSWER', _('No answer')),
('FAILED', _('Failed')),
('BUSY', _('Busy')),
('ANSWERED', _('Answered')),
('UNKNOWN', _('Unknown'))
)
calldate = models.DateTimeField(default='0000-00-00 00:00:00', primary_key=True)
clid = models.CharField(max_length=80, default='')
src = models.CharField(max_length=80, default='')
dst = models.CharField(max_length=80, default='')
dcontext = models.CharField(max_length=80, default='')
channel = models.CharField(max_length=80, default='')
dstchannel = models.CharField(max_length=80, default='')
lastapp = models.CharField(max_length=80, default='')
lastdata = models.CharField(max_length=80, default='')
duration = models.IntegerField(default=0)
billsec = models.IntegerField(default=0)
start = models.DateTimeField(null=True, blank=True, default=None)
answer = models.DateTimeField(null=True, blank=True, default=None)
end = models.DateTimeField(null=True, blank=True, default=None)
disposition = models.CharField(max_length=45, choices=DISPOSITION_CHOICES, default='')
amaflags = models.IntegerField(default=0)
accountcode = models.CharField(max_length=20, default='')
userfield = models.CharField(max_length=255, default='')
uniqueid = models.CharField(max_length=32, default='')
def save(self, *args, **kwargs):
return
def delete(self, *args, **kwargs):
return
def locate_disposition(self):
dsp = self.disposition
if dsp == 'NO ANSWER':
return _('No answer')
elif dsp == 'FAILED':
return _('Failed')
elif dsp == 'BUSY':
return _('Busy')
elif dsp == 'ANSWERED':
return _('Answered')
elif dsp == 'UNKNOWN':
return _('Unknown')
return ''
def path_to_media(self):
path = getattr(settings, 'DIALING_MEDIA', '/media')
if self.userfield == 'request':
return "%s/recording/request" % path
elif self.userfield == 'report':
return "%s/recording/bug" % path
return "%s/monitor" % path
def url(self):
if type(self.calldate) is datetime:
return "%s/%s-%s-%s.wav" % (
self.path_to_media(), self.calldate.strftime('%Y/%m/%d/%H_%M'), self.src, self.dst
)
class Meta:
db_table = 'cdr'
managed = False
ordering = ('-calldate',)
class SMSModel(models.Model):
when = models.DateTimeField(auto_now_add=True)
who = models.CharField(max_length=32)
dev = models.CharField(max_length=20)
text = models.CharField(max_length=255)
class Meta:
db_table = 'sms'
verbose_name = _('SMS')
verbose_name_plural = _('SMS')
ordering = ('-when',)
def __str__(self):
return self.text
class SMSOut(models.Model):
when = models.DateTimeField(_('When'), auto_now_add=True)
dst = models.CharField(_('Telephone'), max_length=16)
text = models.CharField(_('Text'), max_length=255)
SMS_OUT_STATUS = (
('nw', _('New')),
('st', _('Sent')),
('fd', _('Failed'))
)
status = models.CharField(_('Status'), max_length=2, choices=SMS_OUT_STATUS, default='nw')
class Meta:
db_table = 'out_sms'
verbose_name = _('Out SMS')
verbose_name_plural = _('Out SMS')
ordering = ('-when',)
def __str__(self):
return self.text

58
dialing_app/templates/ext.html

@ -1,58 +0,0 @@
{% extends request.is_ajax|yesno:'bajax.html,base.html' %}
{% load i18n %}
{% block breadcrumb %}
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li class="active">{% trans 'Last calls' %}</li>
</ol>
{% endblock %}
{% block page-header %}
{{ title }}
{% endblock %}
{% block main %}
<ul class="nav nav-tabs">
{% url 'dialapp:home' as dialhome %}
<li{% if dialhome == request.path %} class="active"{% endif %}>
<a href="{{ dialhome }}">
{% trans 'Last calls' %}
</a>
</li>
{% url 'dialapp:vmail_request' as dialmail %}
<li{% if dialmail == request.path %} class="active"{% endif %}>
<a href="{{ dialmail }}">
{% trans 'Voice mail request' %}
</a>
</li>
{% url 'dialapp:vmail_report' as dialmail %}
<li{% if dialmail == request.path %} class="active"{% endif %}>
<a href="{{ dialmail }}">
{% trans 'Voice mail report' %}
</a>
</li>
{% url 'dialapp:inbox_sms' as dialsmsin %}
<li{% if dialsmsin == request.path %} class="active"{% endif %}>
<a href="{{ dialsmsin }}">
{% trans 'Inbox sms' %}
</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane active">
{% block content %}{% endblock %}
</div>
</div>
{% endblock %}

37
dialing_app/templates/inbox_sms.html

@ -1,37 +0,0 @@
{% extends request.is_ajax|yesno:'nullcont.htm,ext.html' %}
{% load i18n %}
{% block content %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans 'Inbox sms' %}</h3>
</div>
<div class="list-group scroll-area">
{% for msg in sms_messages %}
<div class="list-group-item">
<h5>From {{ msg.who }}
<small>{{ msg.when|date:'d M, H:i:s' }} via {{ msg.dev }}</small>
</h5>
<pre>{{ msg.text }}</pre>
</div>
{% empty %}
<div class="list-group-item">
<h4 class="list-group-item-heading">{% trans 'Message history is empty' %}</h4>
</div>
{% endfor %}
</div>
<div class="panel-footer">
{% if perms.dialing_app.add_smsout %}
<a href="{% url 'dialapp:send_sms' %}" class="btn btn-default btn-modal">
<span class="glyphicon glyphicon-envelope"></span> {% trans 'Send sms' %}
</a>
{% endif %}
</div>
</div>
{% endblock %}

78
dialing_app/templates/index.html

@ -1,78 +0,0 @@
{% extends request.is_ajax|yesno:'nullcont.htm,ext.html' %}
{% load i18n telephone_filters %}
{% block content %}
<div class="table-responsive">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>{% trans 'Play' %}</th>
<th>{% trans 'calldate' %}</th>
<th>{% trans 'src' %}</th>
<th>{% trans 'dst' %}</th>
<th>{% trans 'duration' %}</th>
<th>{% trans 'start' %}</th>
<th>{% trans 'answer' %}</th>
<th>{% trans 'end' %}</th>
<th>{% trans 'disposition' %}</th>
</tr>
<tr>
<th colspan="9">
<form class="form-inline" action="{% url 'dialapp:vfilter' %}" method="get">
<div class="form-group">
<label class="sr-only" for="dialsearch">{% trans 'Find dials' %}</label>
<div class="input-group input-group-sm">
<input type="text" class="form-control" id="dialsearch" placeholder="{% trans 'Telephone' %}" name="s"{% if s %} value="{{ s }}"{% endif %}>
<div class="input-group-btn">
<button class="btn btn-default" type="submit">
<span class="glyphicon glyphicon-search"></span>
</button>
</div>
</div>
</div>
<div class="form-group">
<label class="sr-only" for="dialtime">{% trans 'Find by dates' %}</label>
<div class="input-group input-group-sm">
<input type="datetime-local" class="form-control" id="dialtime" placeholder="{% trans 'calldate' %}" name="sd"{% if sd %} value="{{ sd }}"{% endif %}>
<div class="input-group-btn">
<button class="btn btn-default" type="submit">
<span class="glyphicon glyphicon-search"></span>
</button>
</div>
</div>
</div>
</form>
</th>
</tr>
</thead>
<tbody>
{% for log in logs %}
<tr>
{% with lurl=log.url %}
<td class="btn-group btn-group-xs btn-group-justify">
<button class="btn btn-default player-btn disabled">
<span class="glyphicon glyphicon-play"></span>
<audio preload="metadata" src="{{ lurl|default:'#' }}"></audio>
</button>
<a href="{{ lurl|default:'#' }}" class="btn btn-default disabled" title="{% trans 'Download' %}">
<span class="glyphicon glyphicon-download-alt"></span>
</a>
</td>
<td>{{ log.calldate|date:'d M, H:i:s' }}</td>
<td>{{ log.src|abon_if_telephone|safe }}</td>
<td>{{ log.dst|abon_if_telephone|safe }}</td>
<td>{{ log.duration }}</td>
<td>{{ log.start|date:'d M, H:i:s' }}</td>
<td>{{ log.answer|date:'d M, H:i:s' }}</td>
<td>{{ log.end|date:'d M, H:i:s' }}</td>
<td>{{ log.locate_disposition }}</td>
{% endwith %}
</tr>
{% empty %}
<tr>
<td colspan="9">{% trans 'Calls was not found' %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}

23
dialing_app/templates/modal_send_sms.html

@ -1,23 +0,0 @@
{% load i18n bootstrap3 %}
<form action="{% url 'dialapp:send_sms' %}?path={{ path|default:'' }}" method="post"> {% csrf_token %}
<div class="modal-header primary">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title"><span class="glyphicon glyphicon-envelope"></span>{% trans 'Send sms' %}</h4>
</div>
{% include '_messages.html' %}
<div class="modal-body">
{% bootstrap_icon 'earphone' as ic %}
{% bootstrap_field form.dst label_class='col-sm-2' field_class='col-sm-10' addon_before=ic %}
{% bootstrap_icon 'pencil' as ic %}
{% bootstrap_field form.text label_class='col-sm-2' field_class='col-sm-10' addon_before=ic %}
<button type="submit" class="btn btn-sm btn-success">
<span class="glyphicon glyphicon-send"></span> {% trans 'Send' %}
</button>
</div>
</form>

48
dialing_app/templates/vmail.html

@ -1,48 +0,0 @@
{% extends request.is_ajax|yesno:'nullcont.htm,ext.html' %}
{% load i18n telephone_filters %}
{% block content %}
<div class="table-responsive">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>{% trans 'Play' %}</th>
<th>{% trans 'calldate' %}</th>
<th>{% trans 'src' %}</th>
<th>{% trans 'duration' %}</th>
<th>{% trans 'start' %}</th>
<th>{% trans 'answer' %}</th>
<th>{% trans 'end' %}</th>
<th>{% trans 'disposition' %}</th>
</tr>
</thead>
<tbody>
{% for vmail in vmessages %}
<tr>
<td class="btn-group btn-group-xs">
<button class="btn btn-default player-btn disabled">
<span class="glyphicon glyphicon-play"></span>
<audio preload="metadata" src="{{ vmail.path_to_media }}/{{ vmail.calldate|date:"YmdHi" }}-{{ vmail.src }}-{{ vmail.dst }}.wav"></audio>
</button>
<a href="{{ vmail.path_to_media }}/{{ vmail.calldate|date:"YmdHi" }}-{{ vmail.src }}-{{ vmail.dst }}.wav" class="btn btn-default disabled" target="_blank">
<span class="glyphicon glyphicon-download-alt"></span>
</a>
</td>
<td>{{ vmail.calldate|date:'d E Y, H:i:s' }}</td>
<td>{{ vmail.src|abon_if_telephone|safe }}</td>
<td>{{ vmail.duration }}</td>
<td>{{ vmail.start|date:'d E Y, H:i:s' }}</td>
<td>{{ vmail.answer|date:'d E Y, H:i:s' }}</td>
<td>{{ vmail.end|date:'d E Y, H:i:s' }}</td>
<td>{{ vmail.locate_disposition }}</td>
</tr>
{% empty %}
<tr>
<td colspan="8">{% trans 'Calls was not found' %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}

0
dialing_app/templatetags/__init__.py

20
dialing_app/templatetags/telephone_filters.py

@ -1,20 +0,0 @@
import re
from django import template
from django.shortcuts import resolve_url
from django.template.defaultfilters import stringfilter
register = template.Library()
@register.filter
@stringfilter
def abon_if_telephone(value):
"""Возвращаем ссыль на абонента если передали номер телефона"""
if re.match(r'^\+?\d+$', value):
if value[0] != '+':
value = '+' + value
url = resolve_url('dialapp:to_abon', tel=value)
a = '<a href="%s">%s</a>' % (url, value)
return a
else:
return value

3
dialing_app/tests.py

@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

15
dialing_app/urls.py

@ -1,15 +0,0 @@
from django.urls import path, re_path
from . import views
app_name = 'dialing_app'
urlpatterns = [
path('', views.LastCallsListView.as_view(), name='home'),
path('filter/', views.DialsFilterListView.as_view(), name='vfilter'),
re_path('^to_abon(?P<tel>\+?\d+)/$', views.to_abon, name='to_abon'),
path('requests/', views.VoiceMailRequestsListView.as_view(), name='vmail_request'),
path('reports/', views.VoiceMailReportsListView.as_view(), name='vmail_report'),
path('sms/in/', views.InboxSMSListView.as_view(), name='inbox_sms'),
path('sms/send/', views.send_sms, name='send_sms'),
path('api/sms/', views.SmsManager.as_view())
]

221
dialing_app/views.py

@ -1,221 +0,0 @@
from datetime import datetime
from subprocess import run
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.db import ProgrammingError
from django.shortcuts import redirect, render
from django.utils.translation import gettext_lazy as _
from django.utils.decorators import method_decorator
from django.views.generic import ListView
from guardian.decorators import permission_required_or_403 as permission_required
from django.db.models import Q
from django.conf import settings
from abonapp.models import Abon
from djing.global_base_views import SecureApiView
from djing import JSONType
from djing.lib import safe_int
from djing.lib.decorators import only_admins, json_view
from .models import AsteriskCDR, SMSModel, SMSOut
from .forms import SMSOutForm
login_decs = login_required, only_admins
class BaseListView(ListView):
http_method_names = 'get',
paginate_by = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10)
@method_decorator(login_decs, name='dispatch')
@method_decorator(permission_required('dialing_app.change_asteriskcdr'), name='dispatch')
class LastCallsListView(BaseListView):
template_name = 'index.html'
context_object_name = 'logs'
queryset = AsteriskCDR.objects.exclude(userfield='request')
def get(self, request, *args, **kwargs):
try:
return super(LastCallsListView, self).get(request, *args, **kwargs)
except ProgrammingError as e:
messages.error(self.request, e)
return redirect('abonapp:group_list')
def get_context_data(self, **kwargs):
context = super(LastCallsListView, self).get_context_data(**kwargs)
context['title'] = _('Last calls')
return context
@login_required
@only_admins
def to_abon(request, tel):
abon = Abon.objects.filter(
Q(telephone__icontains=tel) |
Q(additional_telephones__telephone__icontains=tel)
)
abon_count = abon.count()
if abon_count > 1:
messages.warning(
request, _('Multiple users with the telephone number')
)
elif abon_count == 0:
messages.error(request, _('User with the telephone number not found'))
return redirect('dialapp:home')
abon = abon[0]
if abon.group:
return redirect(
'abonapp:abon_home', gid=abon.group.pk,
uname=abon.username
)
else:
return redirect('abonapp:group_list')
@method_decorator(login_decs, name='dispatch')
class VoiceMailRequestsListView(BaseListView):
template_name = 'vmail.html'
context_object_name = 'vmessages'
queryset = AsteriskCDR.objects.filter(userfield='request')
def get_context_data(self, **kwargs):
context = super(VoiceMailRequestsListView, self).get_context_data(**kwargs)
context['title'] = _('Voice mail request')
return context
class VoiceMailReportsListView(VoiceMailRequestsListView):
queryset = AsteriskCDR.objects.filter(userfield='report')
def get_context_data(self, **kwargs):
context = super(VoiceMailRequestsListView, self).get_context_data(**kwargs)
context['title'] = _('Voice mail report')
return context
@method_decorator(login_decs, name='dispatch')
class DialsFilterListView(BaseListView):
context_object_name = 'logs'
template_name = 'index.html'
def get_context_data(self, **kwargs):
context = super(DialsFilterListView, self).get_context_data(**kwargs)
context['title'] = _('Find dials')
context['s'] = self.request.GET.get('s')
context['sd'] = self.request.GET.get('sd')
return context
def get_queryset(self):
s = self.request.GET.get('s')
sd = self.request.GET.get('sd')
if isinstance(s, str) and s != '':
cdr_q = Q(src__icontains=s) | Q(dst__icontains=s)
else:
cdr_q = None
try:
if isinstance(sd, str) and sd != '':
sd_date = datetime.strptime(sd, '%Y-%m-%d')
if cdr_q:
cdr_q |= Q(calldate__date=sd_date)
else:
cdr_q = Q(calldate__date=sd_date)
except ValueError:
messages.add_message(self.request, messages.ERROR, _('Make sure that your date format is correct'))
if cdr_q is None:
cdr = AsteriskCDR.objects.all()
else:
cdr = AsteriskCDR.objects.filter(cdr_q)
return cdr
@method_decorator(login_decs, name='dispatch')
@method_decorator(permission_required('dialing_app.view_smsmodel'), name='dispatch')
class InboxSMSListView(BaseListView):
template_name = 'inbox_sms.html'
context_object_name = 'sms_messages'
model = SMSModel
@login_required
@only_admins
@permission_required('dialing_app.add_smsout')
def send_sms(request):
path = request.GET.get('path')
initial_dst = request.GET.get('dst')
if request.method == 'POST':
frm = SMSOutForm(request.POST)
if frm.is_valid():
frm.save()
messages.success(request, _('Message was enqueued for sending'))
pidfile_name = '/run/dialing.py.pid'
try:
with open(pidfile_name, 'r') as f:
pid = int(f.read())
run(['/usr/bin/kill', '-SIGUSR1', str(pid)])
except FileNotFoundError:
print('Failed sending, %s not found' % pidfile_name)
if path:
return redirect(path)
else:
return redirect('dialapp:inbox_sms')
else:
messages.error(request, _('fix form errors'))
else:
frm = SMSOutForm(initial={'dst': initial_dst})
return render(request, 'modal_send_sms.html', {
'form': frm,
'path': path
})
class SmsManager(SecureApiView):
#
# Api view for management sms from dongle
#
http_method_names = ('get',)
@staticmethod
def bad_cmd() -> JSONType:
return {'text': 'Command is not allowed'}
@method_decorator(json_view)
def get(self, request, *args, **kwargs):
cmd = request.GET.get('cmd')
data = request.GET.dict()
handler = getattr(self, cmd.lower(), self.bad_cmd)
del data['cmd']
del data['sign']
return handler(**data)
@staticmethod
def save_sms(**kwargs) -> JSONType:
sms = SMSModel.objects.create(
who=kwargs.get('who'),
dev=kwargs.get('dev'),
text=kwargs.get('text')
)
return {'status': 'ok', 'sms_id': sms.pk}
@staticmethod
def update_status(**kwargs) -> JSONType:
msg_id = safe_int(kwargs.get('mid'))
if msg_id != 0:
status = kwargs.get('status')
update_count = SMSOut.objects.filter(pk=msg_id).update(status=status)
return {
'text': 'Status updated',
'update_count': update_count
}
return {'text': 'Bad mid parameter'}
@staticmethod
def get_new() -> JSONType:
msgs = SMSOut.objects.filter(status='nw').defer('status')
res = [{
'when': round(m.timestamp),
'dst': m.dst,
'text': m.text
} for m in msgs]
return res

1
djing/settings.py

@ -57,7 +57,6 @@ INSTALLED_APPS = [
'clientsideapp',
'messenger',
'msg_app',
'dialing_app',
'group_app',
'guardian',
'pinax_theme_bootstrap',

1
djing/urls.py

@ -15,7 +15,6 @@ urlpatterns = [
path('tasks/', include('taskapp.urls', namespace='taskapp')),
path('client/', include('clientsideapp.urls', namespace='client_side')),
path('msg/', include('msg_app.urls', namespace='msg_app')),
path('dialing/', include('dialing_app.urls', namespace='dialapp')),
path('groups/', include('group_app.urls', namespace='group_app')),
path('ip_pool/', include('ip_pool.urls', namespace='ip_pool')),
path('messenger/', include('messenger.urls', namespace='messenger')),

2
docs/install.md

@ -241,7 +241,7 @@ __sha256__. то секретное слово должен знать билл
```
$ ./manage.py migrate
Operations to perform:
Apply all migrations: mapapp, contenttypes, dialing_app, msg_app, taskapp, accounts_app, devapp, statistics, tariff_app, admin, sessions, chatbot, auth, abonapp
Apply all migrations: mapapp, contenttypes, msg_app, taskapp, accounts_app, devapp, statistics, tariff_app, admin, sessions, chatbot, auth, abonapp
Running migrations:
Rendering model states... DONE
Applying mapapp.0001_initial... OK

9
templates/base.html

@ -88,15 +88,6 @@
</a>
</li>
{% if perms.dialing_app.change_asteriskcdr %}
{% url 'dialapp:home' as dialhome %}
<li{% if dialhome in request.path %} class="active"{% endif %}>
<a href="{{ dialhome }}">
<span class="glyphicon glyphicon-phone-alt"></span> {% trans 'Dialing' %}
</a>
</li>
{% endif %}
{% if perms.traf_stat.statcache_view %}
{% url 'traf_stat:home' as stathome %}
<li{% if stathome in request.path %} class="active"{% endif %}>

Loading…
Cancel
Save