Browse Source
Merge branch 'devel' of https://github.com/nerosketch/djing
Merge branch 'devel' of https://github.com/nerosketch/djing
# Conflicts: # README.mddevel
141 changed files with 3886 additions and 2671 deletions
-
3Doc.txt
-
23README.md
-
59abonapp/__init__.py
-
2abonapp/admin.py
-
25abonapp/forms.py
-
599abonapp/locale/ru/LC_MESSAGES/django.po
-
6abonapp/migrations/0014_auto_20170330_1452.py
-
42abonapp/migrations/0021_auto_20170705_1403.py
-
41abonapp/migrations/0022_auto_20170816_1109.py
-
272abonapp/models.py
-
8abonapp/pay_systems.py
-
40abonapp/templates/abonapp/activate_service.html
-
72abonapp/templates/abonapp/buy_tariff.html
-
24abonapp/templates/abonapp/charts.html
-
47abonapp/templates/abonapp/dial_log.html
-
82abonapp/templates/abonapp/editAbon.html
-
5abonapp/templates/abonapp/ext.htm
-
38abonapp/templates/abonapp/modal_addstreet.html
-
6abonapp/templates/abonapp/modal_dev.html
-
38abonapp/templates/abonapp/modal_editstreet.html
-
78abonapp/templates/abonapp/peoples.html
-
119abonapp/templates/abonapp/service.html
-
101abonapp/templates/abonapp/services.html
-
225abonapp/tests.py
-
12abonapp/urls_abon.py
-
330abonapp/views.py
-
32accounts_app/locale/ru/LC_MESSAGES/django.po
-
21accounts_app/migrations/0007_auto_20170816_1109.py
-
2accounts_app/models.py
-
4accounts_app/templates/accounts/index.html
-
39accounts_app/views.py
-
50agent/commands/dhcp.py
-
31agent/core.py
-
140agent/mod_mikrotik.py
-
6agent/netflow/djing_flow.conf
-
35agent/structs.py
-
4bugs.txt
-
15chatbot/locale/ru/LC_MESSAGES/django.po
-
2chatbot/telebot.py
-
111clientsideapp/locale/ru/LC_MESSAGES/django.po
-
6clientsideapp/templates/clientsideapp/ext.html
-
3clientsideapp/templates/clientsideapp/index.html
-
28clientsideapp/templates/clientsideapp/modal_activate_service.html
-
32clientsideapp/templates/clientsideapp/modal_complete_service.html
-
10clientsideapp/templates/clientsideapp/modal_service_buy.html
-
26clientsideapp/templates/clientsideapp/modal_unsubscribe_service.html
-
134clientsideapp/templates/clientsideapp/services.html
-
3clientsideapp/urls.py
-
118clientsideapp/views.py
-
2cron.py
-
1devapp/admin.py
-
10devapp/base_intr.py
-
158devapp/dev_types.py
-
42devapp/forms.py
-
164devapp/locale/ru/LC_MESSAGES/django.po
-
2devapp/migrations/0005_auto_20170502_2232.py
-
48devapp/migrations/0006_auto_20170705_1403.py
-
20devapp/migrations/0007_auto_20170816_1109.py
-
74devapp/models.py
-
34devapp/onu_register.sh
-
24devapp/templates/devapp/add_dev.html
-
18devapp/templates/devapp/custom_dev_page/olt.html
-
42devapp/templates/devapp/custom_dev_page/onu.html
-
89devapp/templates/devapp/custom_dev_page/ports.html
-
38devapp/templates/devapp/dev.html
-
20devapp/templates/devapp/devices.html
-
4devapp/templates/devapp/devices_null_group.html
-
11devapp/templates/devapp/ext.htm
-
93devapp/templates/devapp/manage_ports/add_ports.html
-
60devapp/templates/devapp/manage_ports/list.html
-
37devapp/templates/devapp/manage_ports/modal_add_edit_port.html
-
18devapp/templates/devapp/manage_ports/modal_del_port.html
-
12devapp/urls.py
-
258devapp/views.py
-
73dhcp_lever.py
-
0dialing_app/__init__.py
-
3dialing_app/admin.py
-
5dialing_app/apps.py
-
108dialing_app/locale/ru/LC_MESSAGES/django.po
-
43dialing_app/migrations/0001_initial.py
-
0dialing_app/migrations/__init__.py
-
63dialing_app/models.py
-
40dialing_app/templates/ext.html
-
53dialing_app/templates/index.html
-
57dialing_app/templates/vmail.html
-
0dialing_app/templatetags/__init__.py
-
20dialing_app/templatetags/telephone_filters.py
-
3dialing_app/tests.py
-
9dialing_app/urls.py
-
49dialing_app/views.py
-
38djing/__init__.py
-
0djing/fields.py
-
3djing/formfields.py
-
11djing/settings_example.py
-
1djing/urls.py
-
32djing/utils/load_dot_from_nodeny.py
-
92djing/utils/load_from_nodeny.py
-
45djing/utils/push_snmp_passw.py
-
29djing/utils/save_dot_from_nodeny.py
-
280djing/utils/save_from_nodeny.py
@ -1,59 +0,0 @@ |
|||||
from django.conf import settings |
|
||||
|
|
||||
from netaddr import mac_unix, mac_eui48 |
|
||||
|
|
||||
import importlib |
|
||||
import warnings |
|
||||
|
|
||||
class mac_linux(mac_unix): |
|
||||
"""MAC format with zero-padded all upper-case hex and colon separated""" |
|
||||
word_fmt = '%.2X' |
|
||||
|
|
||||
def default_dialect(eui_obj=None): |
|
||||
# Check to see if a default dialect class has been specified in settings, |
|
||||
# using 'module.dialect_cls' string and use importlib and getattr to retrieve dialect class. 'module' is the module and |
|
||||
# 'dialect_cls' is the class name of the custom dialect. The dialect must either be defined or imported by the module's |
|
||||
# __init__.py if the module is a package. |
|
||||
from .fields import MACAddressField # Remove import at v1.4 |
|
||||
if hasattr(settings, 'MACADDRESS_DEFAULT_DIALECT') and not MACAddressField.dialect: |
|
||||
module, dialect_cls = settings.MACADDRESS_DEFAULT_DIALECT.split('.') |
|
||||
dialect = getattr(importlib.import_module(module), dialect_cls, mac_linux) |
|
||||
return dialect |
|
||||
else: |
|
||||
if MACAddressField.dialect: # Remove this "if" statement at v1.4 |
|
||||
warnings.warn( |
|
||||
"The set_dialect class method on MACAddressField has been deprecated, in favor of the default_dialect " |
|
||||
"utility function and settings.MACADDRESS_DEFAULT_DIALECT. See macaddress.__init__.py source or the " |
|
||||
"project README for more information.", |
|
||||
DeprecationWarning, |
|
||||
) |
|
||||
return MACAddressField.dialect |
|
||||
if eui_obj: |
|
||||
return eui_obj.dialect |
|
||||
else: |
|
||||
return mac_linux |
|
||||
|
|
||||
def format_mac(eui_obj, dialect): |
|
||||
# Format a EUI instance as a string using the supplied dialect class, allowing custom string classes by |
|
||||
# passing directly or as a string, a la 'module.dialect_cls', where 'module' is the module and 'dialect_cls' |
|
||||
# is the class name of the custom dialect. The dialect must either be defined or imported by the module's __init__.py if |
|
||||
# the module is a package. |
|
||||
if not isinstance(dialect, mac_eui48): |
|
||||
if isinstance(dialect, str): |
|
||||
module, dialect_cls = dialect.split('.') |
|
||||
dialect = getattr(importlib.import_module(module), dialect_cls) |
|
||||
eui_obj.dialect = dialect |
|
||||
return str(eui_obj) |
|
||||
|
|
||||
|
|
||||
from pkg_resources import get_distribution, DistributionNotFound |
|
||||
import os.path |
|
||||
|
|
||||
try: |
|
||||
_dist = get_distribution('django-macaddress') |
|
||||
except DistributionNotFound: |
|
||||
__version__ = 'Please install this project with setup.py' |
|
||||
else: |
|
||||
__version__ = _dist.version |
|
||||
VERSION = __version__ # synonym |
|
||||
default_app_config = 'abonapp.apps.AbonappConfig' |
|
||||
@ -0,0 +1,42 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9 on 2017-07-05 14:03 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
import django.db.models.deletion |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('devapp', '0006_auto_20170705_1403'), |
||||
|
('abonapp', '0020_auto_20170517_1655'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.RemoveField( |
||||
|
model_name='abon', |
||||
|
name='opt82', |
||||
|
), |
||||
|
migrations.DeleteModel( |
||||
|
name='Opt82', |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name='abon', |
||||
|
name='dev_port', |
||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='devapp.Port'), |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name='abon', |
||||
|
name='device', |
||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='devapp.Device'), |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name='abon', |
||||
|
name='is_dynamic_ip', |
||||
|
field=models.BooleanField(default=False), |
||||
|
), |
||||
|
migrations.DeleteModel( |
||||
|
name='AbonDevice', |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,41 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9 on 2017-08-16 11:09 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
import django.db.models.deletion |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('abonapp', '0021_auto_20170705_1403'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterModelOptions( |
||||
|
name='abontariff', |
||||
|
options={'permissions': (('can_complete_service', 'Снятие со счёта средств'),)}, |
||||
|
), |
||||
|
migrations.RemoveField( |
||||
|
model_name='abon', |
||||
|
name='current_tariffs', |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name='abon', |
||||
|
name='current_tariff', |
||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='abonapp.AbonTariff'), |
||||
|
), |
||||
|
migrations.AlterUniqueTogether( |
||||
|
name='abontariff', |
||||
|
unique_together=set([]), |
||||
|
), |
||||
|
migrations.RemoveField( |
||||
|
model_name='abontariff', |
||||
|
name='abon', |
||||
|
), |
||||
|
migrations.RemoveField( |
||||
|
model_name='abontariff', |
||||
|
name='tariff_priority', |
||||
|
), |
||||
|
] |
||||
@ -1,40 +0,0 @@ |
|||||
{% extends request.is_ajax|yesno:'bajax.html,base.html' %} |
|
||||
{% load i18n %} |
|
||||
{% block main %} |
|
||||
|
|
||||
|
|
||||
<ol class="breadcrumb"> |
|
||||
<li><span class="glyphicon glyphicon-home"></span></li> |
|
||||
<li><a href="{% url 'abonapp:group_list' %}">{% trans 'User groups' %}</a></li> |
|
||||
<li><a href="{% url 'abonapp:people_list' abon_group.id %}">{{ abon_group.title }}</a></li> |
|
||||
<li><a href="{% url 'abonapp:abon_home' abon_group.id abon.id %}">{{ abon.fio }}</a></li> |
|
||||
<li class="active">{% trans 'Activate service' %}</li> |
|
||||
</ol> |
|
||||
|
|
||||
{% include 'message_block.html' %} |
|
||||
|
|
||||
<div class="panel panel-default"> |
|
||||
<div class="panel-heading"> |
|
||||
<h3 class="panel-title">{% trans 'Activate service' %}</h3> |
|
||||
</div> |
|
||||
<div class="panel-body"> |
|
||||
<form role="form" action="{% url 'abonapp:activate_service' abon_group.id abon.id abtar.id %}" |
|
||||
method="post">{% csrf_token %} |
|
||||
<input name="finish_confirm" value="yes" type="hidden"> |
|
||||
|
|
||||
<p> |
|
||||
{% blocktrans with ballance=abon.ballance deadline=deadline|date:'d F Y, H:i:s' %} |
|
||||
Are you sure that you want activate service for the user?<br> |
|
||||
Note that the account will be removed from his money and open access to the resources of the paid services.<br> |
|
||||
Maintenance cost is {{ amount }}. On account of {{ ballance }}, will be {{ diff }}<br> |
|
||||
It will work until {{ deadline }}{% endblocktrans %} |
|
||||
</p> |
|
||||
|
|
||||
<button type="submit" class="btn btn-sm btn-primary"> |
|
||||
<span class="glyphicon glyphicon-save"></span> {% trans 'Save' %} |
|
||||
</button> |
|
||||
</form> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
{% endblock %} |
|
||||
@ -0,0 +1,47 @@ |
|||||
|
{% 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.path_to_media }}/{{ log.calldate|date:"YmdHi" }}-{{ log.src }}-{{ log.dst }}.wav" 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> |
||||
|
|
||||
|
{% include 'toolbar_page.html' with pag=logs %} |
||||
|
|
||||
|
{% endblock %} |
||||
@ -0,0 +1,38 @@ |
|||||
|
{% load i18n %} |
||||
|
<form role="form" action="{% url 'abonapp:street_add' gid %}" method="post"> {% csrf_token %} |
||||
|
<div class="modal-header primary"> |
||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> |
||||
|
<h4 class="modal-title"><span class="glyphicon glyphicon-plus"></span>{% trans 'Add street' %}</h4> |
||||
|
</div> |
||||
|
|
||||
|
{% include 'message_block.html' %} |
||||
|
|
||||
|
<div class="modal-body"> |
||||
|
<div class="form-group-sm"> |
||||
|
<label for="id_name">{% trans 'Street title' %}</label> |
||||
|
|
||||
|
<div class="input-group"> |
||||
|
<span class="input-group-addon"><span class="glyphicon glyphicon-font"></span></span> |
||||
|
{{ form.name }}{{ form.name.errors }} |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="form-group-sm"> |
||||
|
<label for="id_group">{% trans 'User group' %}</label> |
||||
|
<div class="input-group"> |
||||
|
<span class="input-group-addon"><span class="glyphicon glyphicon-user"></span></span> |
||||
|
{{ form.group }}{{ form.group.errors }} |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="btn-group"> |
||||
|
<button type="submit" class="btn btn-sm btn-success"> |
||||
|
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add' %} |
||||
|
</button> |
||||
|
<button type="reset" class="btn btn-sm btn-default"> |
||||
|
<span class="glyphicon glyphicon-remove-circle"></span> {% trans 'Reset' %} |
||||
|
</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
</form> |
||||
@ -0,0 +1,38 @@ |
|||||
|
{% load i18n %} |
||||
|
<form role="form" action="{% url 'abonapp:street_edit' gid %}" method="post"> {% csrf_token %} |
||||
|
<div class="modal-header primary"> |
||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> |
||||
|
<h4 class="modal-title"><span class="glyphicon glyphicon-edit"></span>{% trans 'Edit streets' %}</h4> |
||||
|
</div> |
||||
|
|
||||
|
{% include 'message_block.html' %} |
||||
|
|
||||
|
<div class="modal-body"> |
||||
|
|
||||
|
{% for street in streets %} |
||||
|
<div class="form-group"> |
||||
|
<div class="input-group input-group-sm"> |
||||
|
<input type="text" class="form-control" value="{{ street.name }}" name="sname"> |
||||
|
<input type="hidden" name="sid" value="{{ street.pk }}"> |
||||
|
<span class="input-group-btn"> |
||||
|
<a href="{% url 'abonapp:street_del' gid street.pk %}" class="btn btn-danger"> |
||||
|
<span class="glyphicon glyphicon-remove"></span> |
||||
|
</a> |
||||
|
</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
{% empty %} |
||||
|
<h4>{% trans 'Streets has not been found' %}</h4> |
||||
|
{% endfor %} |
||||
|
|
||||
|
<div class="btn-group"> |
||||
|
<button type="submit" class="btn btn-sm btn-primary"> |
||||
|
<span class="glyphicon glyphicon-save"></span> {% trans 'Save' %} |
||||
|
</button> |
||||
|
<button type="reset" class="btn btn-sm btn-default"> |
||||
|
<span class="glyphicon glyphicon-remove-circle"></span> {% trans 'Reset' %} |
||||
|
</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
</form> |
||||
@ -0,0 +1,119 @@ |
|||||
|
{% extends request.is_ajax|yesno:'nullcont.htm,abonapp/ext.htm' %} |
||||
|
{% load i18n %} |
||||
|
{% block content %} |
||||
|
|
||||
|
<div class="row"> |
||||
|
<div class="col-sm-6"> |
||||
|
|
||||
|
<div class="panel panel-default"> |
||||
|
<div class="panel-heading"> |
||||
|
<h3 class="panel-title">{% trans "Subscriber's service" %}</h3> |
||||
|
</div> |
||||
|
<div class="panel-body"> |
||||
|
{% if abon_tariff %} |
||||
|
|
||||
|
<dl class="dl-horizontal"> |
||||
|
<dt>{% trans 'Service' %}</dt> |
||||
|
<dd> |
||||
|
{% if abon_tariff.tariff %} |
||||
|
{% if perms.tariff_app.change_tariff %} |
||||
|
<a href="{% url 'tarifs:edit' abon_tariff.tariff.pk %}" title="{{ abon_tariff.time_start|default:'' }}"> |
||||
|
{{ abon_tariff.tariff.title }} |
||||
|
</a> |
||||
|
{% else %} |
||||
|
{{ abon_tariff.tariff.title }} |
||||
|
{% endif %} |
||||
|
{% else %} |
||||
|
<b class="text-danger">{% trans 'We have a problem in DB: AbonTariff instance has no related to service' %}</b> |
||||
|
{% endif %} |
||||
|
</dd> |
||||
|
<dt>{% trans 'Sum' %}</dt> |
||||
|
<dd>{{ abon_tariff.tariff.amount }} {% trans 'currency' %}.</dd> |
||||
|
|
||||
|
<dt>{% trans 'Input speed' %}</dt> |
||||
|
<dd>{{ abon_tariff.tariff.speedIn }}</dd> |
||||
|
|
||||
|
<dt>{% trans 'Output speed' %}</dt> |
||||
|
<dd>{{ abon_tariff.tariff.speedOut }}</dd> |
||||
|
|
||||
|
<dt>{% trans 'Date of start' %}</dt> |
||||
|
<dd>{{ abon_tariff.time_start|date:"d E Y, l H:i" }}</dd> |
||||
|
|
||||
|
<dt>{% trans 'Works until' %}</dt> |
||||
|
<dd>{{ abon_tariff.deadline|date:"d E Y, l H:i" }}</dd> |
||||
|
</dl> |
||||
|
|
||||
|
<blockquote> |
||||
|
<p>{{ abon_tariff.tariff.descr }}</p> |
||||
|
</blockquote> |
||||
|
|
||||
|
{% else %} |
||||
|
{% trans 'Subscriber has no service' %}. |
||||
|
<a href="{% url 'abonapp:pick_tariff' abon_group.pk abon.pk %}"> |
||||
|
{% trans 'Buy service' %} |
||||
|
</a> |
||||
|
{% endif %} |
||||
|
|
||||
|
{% if abon_tariff %} |
||||
|
<a href="{% url 'abonapp:unsubscribe_service' abon_group.pk abon.pk abon_tariff.pk %}" class="btn btn-danger"> |
||||
|
<span class="glyphicon glyphicon-remove-circle"></span> {% trans 'Finish service' %} |
||||
|
</a> |
||||
|
{% endif %} |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-sm-6"> |
||||
|
<div class="panel panel-default"> |
||||
|
<div class="panel-heading"> |
||||
|
<h3 class="panel-title">Услуги для заказа</h3> |
||||
|
</div> |
||||
|
<div class="panel-body"> |
||||
|
<table class="table table-condensed"> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<th>{% trans 'Pick a service' %}</th> |
||||
|
<th>{% trans 'Service' %}</th> |
||||
|
<th>{% trans 'Price' %}</th> |
||||
|
<th>{% trans 'Speed In' %}</th> |
||||
|
<th>{% trans 'Speed Out' %}</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
{% with can_ch_trf=perms.tariff_app.change_tariff %} |
||||
|
{% for service in services %} |
||||
|
<tr> |
||||
|
<td><a href="{% url 'abonapp:pick_tariff' abon_group.pk abon.pk %}?selected_tariff={{ service.pk }}" |
||||
|
class="btn btn-sm btn-default" title="{{ service.get_calc_type_display }}" data-toggle="tooltip"{% if abon_tariff %} disabled{% endif %}> |
||||
|
<span class="glyphicon glyphicon-shopping-cart"></span> |
||||
|
</a></td> |
||||
|
<td> |
||||
|
{% if can_ch_trf %} |
||||
|
<a href="{% url 'tarifs:edit' service.pk %}" title="{{ service.descr }}" data-toggle="tooltip"><b>{{ service.title }}</b></a> |
||||
|
{% else %} |
||||
|
{{ service.title }} |
||||
|
{% endif %} |
||||
|
</td> |
||||
|
<td>{{ service.amount }} {% trans 'currency' %}</td> |
||||
|
<td>{{ service.speedIn }}</td> |
||||
|
<td>{{ service.speedOut }}</td> |
||||
|
</tr> |
||||
|
{% empty %} |
||||
|
<tr><td colspan="5"> |
||||
|
{% trans 'This group has no services' %} |
||||
|
<a href="{% url 'abonapp:ch_group_tariff' abon_group.pk %}" class="btn btn-sm btn-default" title="{% trans 'User groups' %}"> |
||||
|
<span class="glyphicon glyphicon-cog"></span> {% trans 'Tariffs in groups' %} |
||||
|
</a> |
||||
|
</td></tr> |
||||
|
{% endfor %} |
||||
|
{% endwith %} |
||||
|
</tbody> |
||||
|
</table> |
||||
|
<a href="{% url 'abonapp:ch_group_tariff' abon_group.pk %}" class="btn btn-sm btn-default" title="{% trans 'User groups' %}"> |
||||
|
<span class="glyphicon glyphicon-cog"></span> {% trans 'Attach services to group' %} |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
{% endblock %} |
||||
@ -1,101 +0,0 @@ |
|||||
{% extends request.is_ajax|yesno:'nullcont.htm,abonapp/ext.htm' %} |
|
||||
{% load i18n %} |
|
||||
{% block content %} |
|
||||
|
|
||||
<legend>{% trans 'Services of subscriber' %}</legend> |
|
||||
<table class="table table-striped table-bordered"> |
|
||||
<thead> |
|
||||
<tr> |
|
||||
<th width="50">{% trans 'Priority' %}</th> |
|
||||
<th>{% trans 'Service' %}</th> |
|
||||
<th>{% trans 'Sum' %}</th> |
|
||||
<th>{% trans 'Input speed' %}</th> |
|
||||
<th>{% trans 'Output speed' %}</th> |
|
||||
<th>{% trans 'Works until' %}</th> |
|
||||
<th>{% trans 'Do' %}</th> |
|
||||
</tr> |
|
||||
</thead> |
|
||||
|
|
||||
<tbody> |
|
||||
{% for trf in abon_tarifs %} |
|
||||
<tr{% if trf.id == active_abontariff_id %} class="active"{% endif %}> |
|
||||
<td>{{ trf.tariff_priority }}</td> |
|
||||
<td> |
|
||||
|
|
||||
{% if perms.tariff_app.change_tariff %} |
|
||||
<a href="{% url 'tarifs:edit' trf.tariff.id %}" title="{{ trf.time_start|default:'' }}"> |
|
||||
{{ trf.tariff.title }} |
|
||||
</a> |
|
||||
{% else %} |
|
||||
{{ trf.tariff.title }} |
|
||||
{% endif %} |
|
||||
|
|
||||
</td> |
|
||||
<td>{{ trf.tariff.amount }}</td> |
|
||||
<td>{{ trf.tariff.speedIn }}</td> |
|
||||
<td>{{ trf.tariff.speedOut }}</td> |
|
||||
<td>{{ trf.deadline|date:"d E Y, l" }}</td> |
|
||||
{% if trf.id != active_abontariff_id %} |
|
||||
<td class="btn-group"> |
|
||||
|
|
||||
{% if perms.abonapp.can_activate_service %} |
|
||||
{% if not active_abontariff_id %} |
|
||||
<a href="{% url 'abonapp:activate_service' abon_group.id abon.id trf.id %}" |
|
||||
class="btn btn-success btn-sm" title="{% trans 'Activate service' %}"> |
|
||||
<i class="glyphicon glyphicon-shopping-cart"></i> |
|
||||
</a> |
|
||||
{% endif %} |
|
||||
{% endif %} |
|
||||
|
|
||||
<!-- "{ % url 'abonapp:chpriority_tariff' abon_group.id abon.id % }?t={ { trf.id } }&a=up" --> |
|
||||
<a href="#" |
|
||||
class="btn btn-default btn-sm disabled" title="{% trans 'Priority up' %}"> |
|
||||
<i class="glyphicon glyphicon-hand-up"></i> |
|
||||
</a> |
|
||||
|
|
||||
<!-- "{ % url 'abonapp:chpriority_tariff' abon_group.id abon.id % }?t={ { trf.id } }&a=down" --> |
|
||||
<a href="#" |
|
||||
class="btn btn-default btn-sm disabled" title="{% trans 'Priority down' %}"> |
|
||||
<i class="glyphicon glyphicon-hand-down"></i> |
|
||||
</a> |
|
||||
|
|
||||
{% if perms.abonapp.delete_abontariff %} |
|
||||
<a href="{% url 'abonapp:unsubscribe_service' abon_group.id abon.id trf.id %}" |
|
||||
class="btn btn-danger btn-sm" title="{% trans 'Delete service' %}"> |
|
||||
<i class="glyphicon glyphicon-remove"></i> |
|
||||
</a> |
|
||||
{% endif %} |
|
||||
</td> |
|
||||
{% else %} |
|
||||
<td> |
|
||||
<a href="{% url 'abonapp:compl_srv' abon_group.id abon.id trf.id %}" class="btn btn-danger btn-sm"> |
|
||||
<i class="glyphicon glyphicon-remove"></i> {% trans 'Finish service' %} |
|
||||
</a> |
|
||||
</td> |
|
||||
{% endif %} |
|
||||
</tr> |
|
||||
{% empty %} |
|
||||
<tr> |
|
||||
<td colspan="7">{% trans 'Services of subscribers not found' %}. |
|
||||
{% if perms.abonapp.can_buy_tariff %} |
|
||||
<a href="{% url 'abonapp:pick_tariff' abon_group.id abon.id %}" class="lgtbx">{% trans 'Buy' %}</a> |
|
||||
{% endif %} |
|
||||
</td> |
|
||||
</tr> |
|
||||
{% endfor %} |
|
||||
</tbody> |
|
||||
{% if perms.abonapp.can_buy_tariff %} |
|
||||
<tfoot> |
|
||||
<tr> |
|
||||
<th colspan="7"> |
|
||||
<a href="{% url 'abonapp:pick_tariff' abon_group.id abon.id %}" class="btn btn-sm btn-success"> |
|
||||
<span class="glyphicon glyphicon-plus"></span> {% trans 'Buy service' %} |
|
||||
</a> |
|
||||
</th> |
|
||||
</tr> |
|
||||
</tfoot> |
|
||||
{% endif %} |
|
||||
</table> |
|
||||
|
|
||||
|
|
||||
{% endblock %} |
|
||||
@ -1,225 +0,0 @@ |
|||||
from django.shortcuts import resolve_url |
|
||||
from django.test import TestCase |
|
||||
from django.test.client import Client |
|
||||
from agent import NasNetworkError |
|
||||
from .models import AbonTariff, Abon, AbonGroup, AbonRawPassword |
|
||||
from tariff_app.models import Tariff |
|
||||
from mydefs import LogicError |
|
||||
|
|
||||
|
|
||||
class AbonTestCase(TestCase): |
|
||||
def setUp(self): |
|
||||
try: |
|
||||
Tariff.objects.create( |
|
||||
title='test_tariff', |
|
||||
descr='taroff descr', |
|
||||
speedIn=1.2, |
|
||||
speedOut=3.0, |
|
||||
amount=3 |
|
||||
) |
|
||||
abon = Abon() |
|
||||
abon.username = '1234567' |
|
||||
abon.fio = 'mainuser' |
|
||||
abon.telephone = '+79788328884' |
|
||||
abon.set_password('ps') |
|
||||
abon.is_superuser = True |
|
||||
abon.save() |
|
||||
abon_group = AbonGroup.objects.create(title='abon_group') |
|
||||
abon_group.profiles.add(abon) |
|
||||
except NasNetworkError: |
|
||||
pass |
|
||||
|
|
||||
# проверка на пополнение счёта |
|
||||
def test_add_ballance(self): |
|
||||
try: |
|
||||
abon = Abon.objects.get(username='1234567') |
|
||||
ballance = abon.ballance |
|
||||
abon.add_ballance(abon, 13, 'test pay') |
|
||||
abon.save(update_fields=['ballance']) |
|
||||
self.assertEqual(abon.ballance, ballance+13) |
|
||||
ballance = abon.ballance |
|
||||
abon.add_ballance(abon, 5.34, 'test float pay') |
|
||||
abon.save(update_fields=['ballance']) |
|
||||
self.assertEqual(abon.ballance, ballance+5.34) |
|
||||
except NasNetworkError: |
|
||||
pass |
|
||||
|
|
||||
# пробуем выбрать услугу |
|
||||
def test_pick_tariff(self): |
|
||||
try: |
|
||||
tariff = Tariff.objects.get(title='test_tariff') |
|
||||
abon = Abon.objects.get(username='1234567') |
|
||||
try: |
|
||||
abon.pick_tariff(tariff, abon) |
|
||||
# нет денег, должно всплыть исключение и сюда дойти мы не должны |
|
||||
self.assertFalse(True) |
|
||||
except LogicError: |
|
||||
pass |
|
||||
act_tar = abon.active_tariff() |
|
||||
# если недостаточно денег на счету |
|
||||
assert abon.ballance <= tariff.amount |
|
||||
# У абонента на счету 0, не должна быть куплена услуга |
|
||||
self.assertEqual(act_tar, None) |
|
||||
# Раз услуги нет то и доступа быть не должно |
|
||||
self.assertTrue(not abon.is_access()) |
|
||||
|
|
||||
# с деньгами |
|
||||
abon.add_ballance(abon, 7.34, 'add pay for test pick tariff') |
|
||||
abon.pick_tariff(tariff, abon) |
|
||||
act_tar = abon.active_tariff() |
|
||||
# должны получить указанную услугу |
|
||||
self.assertEqual(act_tar, tariff) |
|
||||
# и получить доступ |
|
||||
self.assertTrue(abon.is_access()) |
|
||||
except NasNetworkError: |
|
||||
pass |
|
||||
|
|
||||
# тестим очередь услуг |
|
||||
def test_services_queue(self): |
|
||||
abon = Abon.objects.get(username='1234567') |
|
||||
tariff = Tariff.objects.get(title='test_tariff') |
|
||||
abon.add_ballance(abon, 9, 'add pay for test services queue') |
|
||||
abon.save() |
|
||||
abon.pick_tariff(tariff, abon) |
|
||||
abon.pick_tariff(tariff, abon) |
|
||||
abon.pick_tariff(tariff, abon) |
|
||||
# снять деньги должно было только за первый выбор, остальные стают в очередь услуг |
|
||||
self.assertEqual(abon.ballance, 6) |
|
||||
|
|
||||
c = Client() |
|
||||
# login |
|
||||
c.post(resolve_url('acc_app:login'), {'login': '1234567', 'password': 'ps'}) |
|
||||
url = resolve_url('abonapp:compl_srv', gid=1, uid=1, srvid=1) |
|
||||
resp = c.get(url) |
|
||||
print('RESP:', resp) |
|
||||
self.assertEqual(resp.status_code, 200) |
|
||||
resp = c.post(url, data={ |
|
||||
'finish_confirm': 'yes' |
|
||||
}) |
|
||||
print('RESP:', resp) |
|
||||
# при успешной остановке услуги идёт редирект на др страницу |
|
||||
self.assertEqual(resp.status_code, 302) |
|
||||
# текущей услуги быть не должно |
|
||||
act_tar = abon.active_tariff() |
|
||||
self.assertIsNone(act_tar) |
|
||||
# не активных услуг останется 2 |
|
||||
noact_count = AbonTariff.objects.filter(abon=abon).filter(time_start=None).count() |
|
||||
self.assertEqual(noact_count, 2) |
|
||||
|
|
||||
# проверяем платёжку alltime |
|
||||
def test_allpay(self): |
|
||||
from hashlib import md5 |
|
||||
from djing.settings import pay_SECRET, pay_SERV_ID |
|
||||
import xmltodict |
|
||||
|
|
||||
def sig(act, pay_account, pay_id): |
|
||||
md = md5() |
|
||||
s = '_'.join((str(act), str(pay_account), pay_SERV_ID, str(pay_id), pay_SECRET)) |
|
||||
md.update(bytes(s, 'utf-8')) |
|
||||
return md.hexdigest() |
|
||||
|
|
||||
c = Client() |
|
||||
url = resolve_url('abonapp:terminal_pay') |
|
||||
r = c.get(url, { |
|
||||
'ACT': 1, 'PAY_ACCOUNT': '1234567', |
|
||||
'SERVICE_ID': pay_SERV_ID, |
|
||||
'PAY_ID': 3561234, |
|
||||
'TRADE_POINT': 377, |
|
||||
'SIGN': sig(1, 1234567, 3561234) |
|
||||
}) |
|
||||
xobj = xmltodict.parse(r.content) |
|
||||
self.assertEqual(int(xobj['pay-response']['status_code']), 21) |
|
||||
r = c.get(url, { |
|
||||
'ACT': 4, 'PAY_ACCOUNT': '1234567', |
|
||||
'SERVICE_ID': pay_SERV_ID, |
|
||||
'PAY_ID': 3561234, |
|
||||
'PAY_AMOUNT': 1.0, |
|
||||
'TRADE_POINT': 377, |
|
||||
'SIGN': sig(4, 1234567, 3561234) |
|
||||
}) |
|
||||
xobj = xmltodict.parse(r.content) |
|
||||
self.assertEqual(int(xobj['pay-response']['status_code']), 22) |
|
||||
r = c.get(url, { |
|
||||
'ACT': 4, 'PAY_ACCOUNT': '1234567', |
|
||||
'SERVICE_ID': pay_SERV_ID, |
|
||||
'PAY_ID': 3561234, |
|
||||
'PAY_AMOUNT': 1.0, |
|
||||
'TRADE_POINT': 377, |
|
||||
'SIGN': sig(4, 1234567, 3561234) |
|
||||
}) |
|
||||
xobj = xmltodict.parse(r.content) |
|
||||
self.assertEqual(int(xobj['pay-response']['status_code']), -100) |
|
||||
r = c.get(url, { |
|
||||
'ACT': 7, 'PAY_ACCOUNT': '1234567', |
|
||||
'SERVICE_ID': pay_SERV_ID, |
|
||||
'PAY_ID': 3561234, |
|
||||
'PAY_AMOUNT': 1.0, |
|
||||
'TRADE_POINT': 377, |
|
||||
'SIGN': sig(7, 1234567, 3561234) |
|
||||
}) |
|
||||
xobj = xmltodict.parse(r.content) |
|
||||
self.assertEqual(int(xobj['pay-response']['status_code']), 11) |
|
||||
abon = Abon.objects.get(username='1234567') |
|
||||
self.assertEqual(abon.ballance, 1) |
|
||||
|
|
||||
# пробуем добавить группу абонентов |
|
||||
def test_add_abongroup(self): |
|
||||
abon = Abon.objects.get(username='1234567') |
|
||||
ag = AbonGroup.objects.create(title='%&34%$&*(') |
|
||||
ag.profiles.add(abon) |
|
||||
|
|
||||
# пробуем добавить абонента |
|
||||
def test_add_abon(self): |
|
||||
c = Client() |
|
||||
c.login(username='1234567', password='ps') |
|
||||
url = resolve_url('abonapp:add_abon', gid=1) |
|
||||
r = c.get(url) |
|
||||
# поглядим на страницу добавления абонента |
|
||||
self.assertEqual(r.status_code, 200) |
|
||||
r = c.post(url, { |
|
||||
'username': '123', |
|
||||
'password': 'ps', |
|
||||
'fio': 'Abon Fio', |
|
||||
'telephone': '+79783753914', |
|
||||
'is_active': True |
|
||||
}) |
|
||||
self.assertEqual(r.status_code, 302) |
|
||||
r = c.get(resolve_url('abonapp:add_abon', gid=324)) |
|
||||
self.assertEqual(r.status_code, 404) |
|
||||
try: |
|
||||
abn = Abon.objects.get(username='123') |
|
||||
self.assertIsNotNone(abn) |
|
||||
psw = AbonRawPassword.objects.get(account=abn, passw_text='ps') |
|
||||
self.assertIsNotNone(psw) |
|
||||
except Abon.DoesNotExist: |
|
||||
# абонент должен был создаться |
|
||||
self.assertTrue(False) |
|
||||
except AbonRawPassword.DoesNotExist: |
|
||||
# должен быть пароль абонента простым текстом |
|
||||
self.assertTrue(False) |
|
||||
|
|
||||
# пробуем удалить абонента |
|
||||
def test_view_delentity(self): |
|
||||
c = Client() |
|
||||
c.login(username='1234567', password='ps') |
|
||||
url = resolve_url('abonapp:del_abon') + '?t=a&id=1' |
|
||||
r = c.get('/abons/1/addabon') |
|
||||
|
|
||||
|
|
||||
class AbonTariffTestCase(TestCase): |
|
||||
def setUp(self): |
|
||||
abon = Abon.objects.create( |
|
||||
username='1234567', |
|
||||
telephone='+79788328884' |
|
||||
) |
|
||||
tariff = Tariff.objects.create( |
|
||||
title='test_tariff', |
|
||||
descr='taroff descr', |
|
||||
speedIn=1.2, |
|
||||
speedOut=3.0, |
|
||||
amount=3 |
|
||||
) |
|
||||
AbonTariff.objects.create( |
|
||||
abon=abon, |
|
||||
tariff=tariff |
|
||||
) |
|
||||
@ -0,0 +1,21 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9 on 2017-08-16 11:09 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
import django.core.validators |
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('accounts_app', '0006_auto_20170416_1029'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterField( |
||||
|
model_name='userprofile', |
||||
|
name='telephone', |
||||
|
field=models.CharField(max_length=16, validators=[django.core.validators.RegexValidator('^\\+[7,8,9,3]\\d{10,11}$')], verbose_name='Телефон'), |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,50 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from django.core.exceptions import MultipleObjectsReturned |
||||
|
from django.utils.translation import ugettext as _ |
||||
|
from abonapp.models import Abon |
||||
|
from devapp.models import Device, Port |
||||
|
|
||||
|
|
||||
|
def dhcp_commit(client_ip, client_mac, switch_mac, switch_port): |
||||
|
try: |
||||
|
dev = Device.objects.get(mac_addr=switch_mac) |
||||
|
mngr_class = dev.get_manager_klass() |
||||
|
|
||||
|
port = _('<never mind>') |
||||
|
if mngr_class.is_use_device_port(): |
||||
|
port = Port.objects.get(device=dev, num=switch_port) |
||||
|
abon = Abon.objects.get(dev_port=port, device=dev) |
||||
|
else: |
||||
|
abon = Abon.objects.get(device=dev) |
||||
|
if not abon.is_dynamic_ip: |
||||
|
print('D:', _('User settings is not dynamic')) |
||||
|
return |
||||
|
if not abon.is_access(): |
||||
|
print('D:', _('User is not access to service')) |
||||
|
return |
||||
|
abon.ip_address = client_ip |
||||
|
abon.is_dhcp = True |
||||
|
abon.save(update_fields=['ip_address']) |
||||
|
print('S:', _("Ip address:'%s' update for '%s' successfull, on port: %s") % (client_ip, abon.get_short_name(), port)) |
||||
|
except Abon.DoesNotExist: |
||||
|
print('N:', _("User with device '%s' does not exist") % dev) |
||||
|
except Device.DoesNotExist: |
||||
|
print('N:', _('Device with mac %s not found') % switch_mac) |
||||
|
except Port.DoesNotExist: |
||||
|
print('N:', _('Port %d on device with mac %s does not exist') % (int(switch_port), switch_mac)) |
||||
|
except MultipleObjectsReturned as e: |
||||
|
print('E:', 'MultipleObjectsReturned:', type(e), e) |
||||
|
|
||||
|
|
||||
|
def dhcp_expiry(client_ip): |
||||
|
try: |
||||
|
abon = Abon.objects.get(ip_address=client_ip) |
||||
|
abon.ip_address = None |
||||
|
abon.is_dhcp = True |
||||
|
abon.save(update_fields=['ip_address']) |
||||
|
except Abon.DoesNotExist: |
||||
|
pass |
||||
|
|
||||
|
|
||||
|
def dhcp_release(client_ip): |
||||
|
dhcp_expiry(client_ip) |
||||
@ -1,6 +0,0 @@ |
|||||
# Config for djing flow |
|
||||
|
|
||||
version = "0.1"; |
|
||||
|
|
||||
# количество строк на запрос |
|
||||
mysql_rows_per_request = 65735; |
|
||||
@ -1,28 +0,0 @@ |
|||||
<form action="{% url 'client_side:activate_service' abtar.pk %}" method="post">{% csrf_token %} |
|
||||
<div class="modal-header primary"> |
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> |
|
||||
<h4 class="modal-title"><span class="glyphicon glyphicon-question-sign"></span>Активировать услугу</h4> |
|
||||
</div> |
|
||||
<div class="modal-body"> |
|
||||
<h3>Вы уверены что хотите активировать услугу?</h3> |
|
||||
<input type="hidden" name="finish_confirm" value="yes"> |
|
||||
<h3>{{ service.title }}</h3> |
|
||||
|
|
||||
<p>{{ service.descr }}</p> |
|
||||
|
|
||||
<!--<p>Входящая скорость: {{ service.speedIn }} MBit/s<br> |
|
||||
Исходящая скорость: {{ service.speedOut }} MBit/s</p>--> |
|
||||
|
|
||||
<p>Вы уверены что хотите активировать эту услугу?<br> |
|
||||
Обратите внимание что с вашего счёта <b>снимутся деньги</b> и откроется доступ к ресурсам оплаченной |
|
||||
услуги.<br> |
|
||||
Стоимость услуги: {{ amount }}руб. На счету {{ abon.ballance }} руб, останется {{ diff }} руб.</p> |
|
||||
|
|
||||
</div> |
|
||||
<div class="modal-footer"> |
|
||||
<button type="submit" class="btn btn-sm btn-success"> |
|
||||
<span class="glyphicon glyphicon-shopping-cart"></span> Активировать |
|
||||
</button> |
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Закрыть</button> |
|
||||
</div> |
|
||||
</form> |
|
||||
@ -1,32 +0,0 @@ |
|||||
<form action="{% url 'client_side:complete_service' abtar.pk %}" method="post">{% csrf_token %} |
|
||||
<div class="modal-header primary"> |
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> |
|
||||
<h4 class="modal-title"><span class="glyphicon glyphicon-question-sign"></span>Завершить услугу</h4> |
|
||||
</div> |
|
||||
<div class="modal-body"> |
|
||||
<h3>Вы уверены что хотите завершить услугу?</h3> |
|
||||
<input type="hidden" name="finish_confirm" value="yes"> |
|
||||
<h3>{{ service.title }}</h3> |
|
||||
|
|
||||
<p>{{ service.descr }}</p> |
|
||||
|
|
||||
<p>Входящая скорость: {{ service.speedIn }} MBit/s<br> |
|
||||
Исходящая скорость: {{ service.speedOut }} MBit/s</p> |
|
||||
|
|
||||
<p>Завершение услуги приведёт к прекращению действия услуги. Т.е. интернет отключится.<br> |
|
||||
Деньги за неиспользованные ресурсы возвращены не будут.<br> |
|
||||
Для возобновления обслуживания вы должны купить новую услугу.</p> |
|
||||
|
|
||||
Услуга была подключена: {{ abtar.time_start|date:'d F Y, H:i:s' }}<br/> |
|
||||
Сегодня: {% now "d F Y, H:i:s" %}<br/> |
|
||||
Время использования: {{ time_use }}<br/> |
|
||||
Полная стоимость услуги: {{ service.amount }}<br/> |
|
||||
<b>Итоговая стоимость: {{ abtar.calc_amount_service }}</b> |
|
||||
</div> |
|
||||
<div class="modal-footer"> |
|
||||
<button type="submit" class="btn btn-sm btn-danger"> |
|
||||
<span class="glyphicon glyphicon-alert"></span> Завершить |
|
||||
</button> |
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Закрыть</button> |
|
||||
</div> |
|
||||
</form> |
|
||||
@ -1,26 +0,0 @@ |
|||||
{% load i18n %} |
|
||||
<form action="{% url 'client_side:unsubscribe_service' abtar.pk %}" method="post">{% csrf_token %} |
|
||||
<div class="modal-header primary"> |
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> |
|
||||
<h4 class="modal-title"><span class="glyphicon glyphicon-question-sign"></span>{% trans 'Unsubscribe from service' %}</h4> |
|
||||
</div> |
|
||||
<div class="modal-body"> |
|
||||
<h3>{% trans 'Are you sure you want to unsubscribe from the service?' %}</h3> |
|
||||
<input type="hidden" name="finish_confirm" value="yes"> |
|
||||
<h3>{{ service.title }}</h3> |
|
||||
|
|
||||
<p>{{ service.descr }}</p> |
|
||||
|
|
||||
<p>{% blocktrans %}Inbound speed: {{ service.speedIn }} MBit/s<br>Outgoing speed: {{ service.speedOut }} MBit/s{% endblocktrans %}</p> |
|
||||
|
|
||||
<p>{% blocktrans %}When you unsubscribe from the service, it just will remove it from the queue inclusions your services.<br> |
|
||||
Your funds will not be affected, the money will not go away.{% endblocktrans %}</p> |
|
||||
|
|
||||
</div> |
|
||||
<div class="modal-footer"> |
|
||||
<button type="submit" class="btn btn-sm btn-primary"> |
|
||||
<span class="glyphicon glyphicon-alert"></span> {% trans 'Unsubscribe' %} |
|
||||
</button> |
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{% trans 'Close' %}</button> |
|
||||
</div> |
|
||||
</form> |
|
||||
@ -0,0 +1,48 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9 on 2017-07-05 14:03 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
import django.db.models.deletion |
||||
|
import djing.fields |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('devapp', '0005_auto_20170502_2232'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.RemoveField( |
||||
|
model_name='portstates', |
||||
|
name='port', |
||||
|
), |
||||
|
migrations.RemoveField( |
||||
|
model_name='port', |
||||
|
name='speed', |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name='device', |
||||
|
name='mac_addr', |
||||
|
field=djing.fields.MACAddressField(blank=True, integer=True, null=True, unique=True), |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name='device', |
||||
|
name='parent_dev', |
||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='devapp.Device'), |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name='port', |
||||
|
name='descr', |
||||
|
field=models.CharField(blank=True, max_length=60, null=True), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='device', |
||||
|
name='devtype', |
||||
|
field=models.CharField(choices=[('Dl', 'DLink switch'), ('Pn', 'PON OLT'), ('On', 'PON ONU')], default='Dl', max_length=2), |
||||
|
), |
||||
|
migrations.DeleteModel( |
||||
|
name='PortStates', |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,20 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9 on 2017-08-16 11:09 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('devapp', '0006_auto_20170705_1403'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterField( |
||||
|
model_name='device', |
||||
|
name='devtype', |
||||
|
field=models.CharField(choices=[('Dl', 'DLink switch'), ('Pn', 'PON OLT'), ('On', 'PON ONU'), ('Ex', 'Eltex switch')], default='Dl', max_length=2), |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,34 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
|
|
||||
|
# old mac address |
||||
|
if [[ $1 =~ ^([0-9A-Fa-f]{1,2}[:-]){5}([0-9A-Fa-f]{1,2})$ ]]; then |
||||
|
MAC=$1 |
||||
|
else |
||||
|
echo "Bad mac $MAC addr" |
||||
|
exit |
||||
|
fi |
||||
|
|
||||
|
|
||||
|
# part code |
||||
|
if [[ $2 =~ ^[a-zA-Z]+$ ]]; then |
||||
|
PART_CODE=$2 |
||||
|
else |
||||
|
echo 'code must contains only letters' |
||||
|
exit |
||||
|
fi |
||||
|
|
||||
|
|
||||
|
DHCP_PATH='/etc/dhcp/macs' |
||||
|
PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/bin |
||||
|
|
||||
|
|
||||
|
if grep "${MAC}" "${DHCP_PATH}/${PART_CODE}.conf" > /dev/null; then |
||||
|
# mac is already exists |
||||
|
exit |
||||
|
else |
||||
|
# add new mac |
||||
|
echo "subclass \"${PART_CODE}\" \"${MAC}\";" >> "${DHCP_PATH}/${PART_CODE}.conf" |
||||
|
/usr/bin/sudo /usr/bin/systemctl restart dhcpd.service |
||||
|
fi |
||||
|
|
||||
@ -0,0 +1,42 @@ |
|||||
|
{% extends request.is_ajax|yesno:'nullcont.htm,devapp/ext.htm' %} |
||||
|
{% load i18n %} |
||||
|
{% block content %} |
||||
|
|
||||
|
<div class="row"> |
||||
|
<div class="col-sm-12"> |
||||
|
<div class="panel panel-default"> |
||||
|
<div class="panel-heading"> |
||||
|
<div class="panel-title">{{ dev.get_devtype_display|default:_('Title of the type of switch') }}. |
||||
|
{% if uptime %} |
||||
|
{% trans 'Uptime' %} {{ uptime }} |
||||
|
{% endif %} |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="panel-body"> |
||||
|
<ul class="list-group"> |
||||
|
<li class="list-group-item">{% trans 'Ip address' %}: {{ dev.ip_address }}</li> |
||||
|
<li class="list-group-item">{% trans 'Mac' %}: {{ dev.mac_addr }}</li> |
||||
|
<li class="list-group-item">{% trans 'Description' %} {{ dev.comment }}</li> |
||||
|
{% for da in dev_accs %} |
||||
|
<li class="list-group-item">{% trans 'Attached user' %}: |
||||
|
{% if da.group %} |
||||
|
<a href="{% url 'abonapp:abon_home' da.group.pk da.pk %}" target="_blank">{{ da.get_full_name }}</a> |
||||
|
{% else %} |
||||
|
{{ da.get_full_name }} |
||||
|
{% endif %} |
||||
|
</li> |
||||
|
{% endfor %} |
||||
|
{% if dev.parent_dev %} |
||||
|
<li class="list-group-item"> |
||||
|
{% with pdev=dev.parent_dev pdgrp=dev.parent_dev.user_group %} |
||||
|
{% trans 'Parent device' %}: <a href="{% url 'devapp:view' pdgrp.pk pdev.pk %}" title="{{ pdev.mac_addr|default:'' }}" target="_blank">{{ pdev.ip_address }} {{ pdev.comment }}</a> |
||||
|
{% endwith %} |
||||
|
</li> |
||||
|
{% endif %} |
||||
|
</ul> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
{% endblock %} |
||||
@ -0,0 +1,93 @@ |
|||||
|
{% extends request.is_ajax|yesno:'bajax.html,base.html' %} |
||||
|
{% load i18n %} |
||||
|
{% block main %} |
||||
|
|
||||
|
<ol class="breadcrumb"> |
||||
|
<li><span class="glyphicon glyphicon-home"></span></li> |
||||
|
<li><a href="{% url 'devapp:group_list' %}">{% trans 'Groups' %}</a></li> |
||||
|
<li><a href="{% url 'devapp:devs' dev.user_group.pk %}">{{ dev.user_group.title }}</a></li> |
||||
|
<li><a href="{% url 'devapp:view' dev.user_group.pk dev.pk %}">{{ dev.comment }}</a></li> |
||||
|
<li class="active">{% trans 'Add ports' %}</li> |
||||
|
</ol> |
||||
|
|
||||
|
{% include 'message_block.html' %} |
||||
|
|
||||
|
<div class="page-header"> |
||||
|
<h2>{{ dev.comment|default:_('Not assigned') }}</h2> |
||||
|
</div> |
||||
|
|
||||
|
<div class="panel panel-default"> |
||||
|
<div class="panel-heading"> |
||||
|
<h3 class="panel-title">{{ dev.comment }}</h3> |
||||
|
</div> |
||||
|
<div class="panel-body"> |
||||
|
|
||||
|
<form class="table-responsive" role="form" action="{% url 'devapp:add_ports' dev.user_group.pk dev.pk %}" method="post">{% csrf_token %} |
||||
|
|
||||
|
<table class="table table-striped table-bordered"> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<th width="10">#</th> |
||||
|
<th>№</th> |
||||
|
<th>{% trans 'Mode' %}</th> |
||||
|
<th>{% trans 'Description' %}</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
{% with gid=dev.user_group.pk did=dev.pk can_del_port=perms.devapp.delete_port %} |
||||
|
{% for port in ports %} |
||||
|
<tr> |
||||
|
<td>{% if port.status %} |
||||
|
<span class="glyphicon glyphicon-ok text-success"></span> |
||||
|
{% else %} |
||||
|
<span class="glyphicon glyphicon-warning-sign text-danger"></span> |
||||
|
{% endif %}</td> |
||||
|
<td>{{ port.pid }}</td> |
||||
|
<td>{{ port.mode }}</td> |
||||
|
<td class="input-group"> |
||||
|
<input type="text" class="form-control input-sm" name="p_text" value="{{ port.text }}"> |
||||
|
<input type="hidden" name="pids" value="{{ port.pid }}"> |
||||
|
<span class="input-group-btn"> |
||||
|
{% if port.from_db %} |
||||
|
{% if can_del_port %} |
||||
|
<a href="{% url 'devapp:del_port' gid did port.pk %}" class="btn btn-sm btn-danger btn-modal" title="{% trans 'Delete' %}"> |
||||
|
{% else %} |
||||
|
<a href="#" class="btn btn-danger btn-sm disabled" title="{% trans 'Delete' %}"> |
||||
|
{% endif %} |
||||
|
<span class="glyphicon glyphicon-remove"></span> |
||||
|
</a> |
||||
|
{% else %} |
||||
|
<a href="{% url 'devapp:add_port' gid did %}?n={{ port.pid }}&t={{ port.text }}" class="btn btn-sm btn-success btn-modal" title="{% trans 'Add' %}"> |
||||
|
<span class="glyphicon glyphicon-plus"></span> |
||||
|
</a> |
||||
|
{% endif %} |
||||
|
</span> |
||||
|
</td> |
||||
|
</tr> |
||||
|
{% endfor %} |
||||
|
{% endwith %} |
||||
|
</tbody> |
||||
|
<tfoot> |
||||
|
<tr> |
||||
|
<td colspan="4" class="btn-group"> |
||||
|
{% if perms.devapp.add_port and ports %} |
||||
|
<button type="submit" class="btn btn-primary"> |
||||
|
<span class="glyphicon glyphicon-save"></span> {% trans 'Save' %} |
||||
|
</button> |
||||
|
{% else %} |
||||
|
<button type="button" class="btn btn-primary" disabled> |
||||
|
<span class="glyphicon glyphicon-save"></span> {% trans 'Save' %} |
||||
|
</button> |
||||
|
{% endif %} |
||||
|
</td> |
||||
|
</tr> |
||||
|
</tfoot> |
||||
|
</table> |
||||
|
|
||||
|
|
||||
|
|
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
{% endblock %} |
||||
@ -0,0 +1,60 @@ |
|||||
|
{% extends request.is_ajax|yesno:'nullcont.htm,devapp/ext.htm' %} |
||||
|
{% load i18n %} |
||||
|
{% block content %} |
||||
|
|
||||
|
<div class="row"> |
||||
|
<div class="col-sm-12"> |
||||
|
<div class="table-responsive"> |
||||
|
<table class="table table-striped table-bordered"> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<th width="50">{% trans 'Number' %}</th> |
||||
|
<th>{% trans 'Description' %}</th> |
||||
|
<th width="100">#</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
|
||||
|
<tbody> |
||||
|
{% with gid=dev.user_group.pk did=dev.pk can_del_port=perms.devapp.delete_port can_edit_port=perms.devapp.change_port %} |
||||
|
{% for port in ports %} |
||||
|
<tr> |
||||
|
<td>{{ port.num }}</td> |
||||
|
<td>{{ port.descr }}</td> |
||||
|
<td class="btn-group btn-group-sm"> |
||||
|
{% if can_del_port %} |
||||
|
<a href="{% url 'devapp:del_port' gid did port.pk %}" class="btn btn-danger btn-modal" title="{% trans 'Delete' %}"> |
||||
|
<span class="glyphicon glyphicon-remove-circle"></span> |
||||
|
</a> |
||||
|
{% endif %} |
||||
|
{% if can_edit_port %} |
||||
|
<a href="{% url 'devapp:edit_port' gid did port.pk %}" class="btn btn-primary btn-modal" title="{% trans 'Edit' %}"> |
||||
|
<span class="glyphicon glyphicon-edit"></span> |
||||
|
</a> |
||||
|
{% endif %} |
||||
|
</td> |
||||
|
</tr> |
||||
|
{% empty %} |
||||
|
<tr> |
||||
|
<td colspan="3">{% trans 'Ports not found' %}</td> |
||||
|
</tr> |
||||
|
{% endfor %} |
||||
|
{% endwith %} |
||||
|
</tbody> |
||||
|
<tfoot> |
||||
|
<tr> |
||||
|
<td colspan="3" class="btn-group"> |
||||
|
{% if perms.devapp.add_port %} |
||||
|
<a href="{% url 'devapp:add_ports' dev.user_group.pk dev.pk %}" class="btn btn-sm btn-default" title="{% trans 'Add' %}"> |
||||
|
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add ports' %} |
||||
|
</a> |
||||
|
{% endif %} |
||||
|
</td> |
||||
|
</tr> |
||||
|
</tfoot> |
||||
|
|
||||
|
</table> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
{% endblock %} |
||||
@ -0,0 +1,37 @@ |
|||||
|
{% load i18n %} |
||||
|
|
||||
|
{% if port_id %} |
||||
|
<form role="form" action="{% url 'devapp:edit_port' gid did port_id %}" method="post">{% else %} |
||||
|
<form role="form" action="{% url 'devapp:add_port' gid did %}" method="post">{% endif %}{% csrf_token %} |
||||
|
<input type="hidden" value="yes" name="confirm"> |
||||
|
<div class="modal-header primary"> |
||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> |
||||
|
<h4 class="modal-title"><span class="glyphicon glyphicon-exclamation-sign"></span>{% trans 'Are you sure?' %}</h4> |
||||
|
</div> |
||||
|
|
||||
|
<div class="modal-body"> |
||||
|
|
||||
|
<div class="form-group"> |
||||
|
<label for="id_num">{% trans 'Number' %}</label> |
||||
|
|
||||
|
<div class="input-group"> |
||||
|
<span class="input-group-addon"><span class="glyphicon glyphicon-bishop"></span></span> |
||||
|
{{ form.num }}{{ form.num.errors }} |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="form-group"> |
||||
|
<label for="id_descr">{% trans 'Description' %}</label> |
||||
|
|
||||
|
<div class="input-group"> |
||||
|
<span class="input-group-addon"><span class="glyphicon glyphicon-comment"></span></span> |
||||
|
{{ form.descr }}{{ form.descr.errors }} |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<button type="submit" class="btn btn-sm btn-primary"> |
||||
|
<span class="glyphicon glyphicon-save"></span> {% trans 'Save' %} |
||||
|
</button> |
||||
|
</div> |
||||
|
|
||||
|
</form> |
||||
@ -0,0 +1,18 @@ |
|||||
|
{% load i18n %} |
||||
|
|
||||
|
<form role="form" action="{% url 'devapp:del_port' grp did port_id %}" method="post">{% csrf_token %} |
||||
|
<input type="hidden" value="yes" name="confirm"> |
||||
|
<div class="modal-header primary"> |
||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> |
||||
|
<h4 class="modal-title"><span class="glyphicon glyphicon-exclamation-sign"></span>{% trans 'Are you sure?' %}</h4> |
||||
|
</div> |
||||
|
|
||||
|
<div class="modal-body"> |
||||
|
<p>{% trans 'Are you sure that you want to delete switch port from db?' %}</p> |
||||
|
|
||||
|
<button type="submit" class="btn btn-sm btn-danger"> |
||||
|
<span class="glyphicon glyphicon-remove"></span> {% trans 'Delete' %} |
||||
|
</button> |
||||
|
</div> |
||||
|
|
||||
|
</form> |
||||
@ -0,0 +1,3 @@ |
|||||
|
from django.contrib import admin |
||||
|
|
||||
|
# Register your models here. |
||||
@ -0,0 +1,5 @@ |
|||||
|
from django.apps import AppConfig |
||||
|
|
||||
|
|
||||
|
class DialingAppConfig(AppConfig): |
||||
|
name = 'dialing_app' |
||||
@ -0,0 +1,108 @@ |
|||||
|
# 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: 2017-05-22 11: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" |
||||
|
|
||||
|
#: dialing_app/models.py:8 dialing_app/models.py:43 |
||||
|
msgid "No answer" |
||||
|
msgstr "Не отвечен" |
||||
|
|
||||
|
#: dialing_app/models.py:9 dialing_app/models.py:45 |
||||
|
msgid "Failed" |
||||
|
msgstr "С ошибкой" |
||||
|
|
||||
|
#: dialing_app/models.py:10 dialing_app/models.py:47 |
||||
|
msgid "Busy" |
||||
|
msgstr "Занято" |
||||
|
|
||||
|
#: dialing_app/models.py:11 dialing_app/models.py:49 |
||||
|
msgid "Answered" |
||||
|
msgstr "Отвечен" |
||||
|
|
||||
|
#: dialing_app/models.py:12 dialing_app/models.py:51 |
||||
|
msgid "Unknown" |
||||
|
msgstr "Не определён" |
||||
|
|
||||
|
#: dialing_app/templates/index.html:9 |
||||
|
msgid "Dialing" |
||||
|
msgstr "Звонки" |
||||
|
|
||||
|
#: dialing_app/templates/index.html:12 |
||||
|
msgid "Last calls" |
||||
|
msgstr "Последние звонки" |
||||
|
|
||||
|
#: dialing_app/templates/index.html:20 |
||||
|
msgid "Play" |
||||
|
msgstr "Слушать" |
||||
|
|
||||
|
#: dialing_app/templates/index.html:21 |
||||
|
msgid "calldate" |
||||
|
msgstr "дата звонка" |
||||
|
|
||||
|
#: dialing_app/templates/index.html:22 |
||||
|
msgid "src" |
||||
|
msgstr "кто" |
||||
|
|
||||
|
#: dialing_app/templates/index.html:23 |
||||
|
msgid "dst" |
||||
|
msgstr "куда" |
||||
|
|
||||
|
#: dialing_app/templates/index.html:24 |
||||
|
msgid "duration" |
||||
|
msgstr "продолжительность" |
||||
|
|
||||
|
#: dialing_app/templates/index.html:25 |
||||
|
msgid "start" |
||||
|
msgstr "начало" |
||||
|
|
||||
|
#: dialing_app/templates/index.html:26 |
||||
|
msgid "answer" |
||||
|
msgstr "ответ" |
||||
|
|
||||
|
#: dialing_app/templates/index.html:27 |
||||
|
msgid "end" |
||||
|
msgstr "конец" |
||||
|
|
||||
|
#: dialing_app/templates/index.html:28 |
||||
|
msgid "disposition" |
||||
|
msgstr "состояние" |
||||
|
|
||||
|
#: dialing_app/templates/index.html:50 |
||||
|
msgid "Calls was not found" |
||||
|
msgstr "Звонки не найдены" |
||||
|
|
||||
|
#: dialing_app/views.py:27 |
||||
|
msgid "Multiple users with the telephone number" |
||||
|
msgstr "Несколько абонентов с указанным номером телефона" |
||||
|
|
||||
|
#: dialing_app/views.py:29 |
||||
|
msgid "User with the telephone number not found" |
||||
|
msgstr "Абонент с таким номером телефона не найден" |
||||
|
|
||||
|
msgid "Voice mail" |
||||
|
msgstr "Оставленные сообщения" |
||||
|
|
||||
|
msgid "Type" |
||||
|
msgstr "Тип" |
||||
|
|
||||
|
msgid "Request" |
||||
|
msgstr "Заявка" |
||||
|
|
||||
|
msgid "Report" |
||||
|
msgstr "Поломка" |
||||
@ -0,0 +1,43 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9 on 2017-05-30 13:33 |
||||
|
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', |
||||
|
}, |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,63 @@ |
|||||
|
from django.db import models |
||||
|
from django.utils.translation import ugettext_lazy as _ |
||||
|
from djing 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 |
||||
|
|
||||
|
class Meta: |
||||
|
db_table = 'cdr' |
||||
@ -0,0 +1,40 @@ |
|||||
|
{% extends request.is_ajax|yesno:'bajax.html,base.html' %} |
||||
|
{% load i18n %} |
||||
|
{% block main %} |
||||
|
|
||||
|
<ol class="breadcrumb"> |
||||
|
<li><span class="glyphicon glyphicon-home"></span></li> |
||||
|
<li class="active">{% trans 'Last calls' %}</li> |
||||
|
</ol> |
||||
|
|
||||
|
{% include 'message_block.html' %} |
||||
|
|
||||
|
<div class="page-header"> |
||||
|
<h3>{{ title }}</h3> |
||||
|
</div> |
||||
|
|
||||
|
<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' as dialmail %} |
||||
|
<li{% if dialmail == request.path %} class="active"{% endif %}> |
||||
|
<a href="{{ dialmail }}"> |
||||
|
{% trans 'Voice mail' %} |
||||
|
</a> |
||||
|
</li> |
||||
|
|
||||
|
</ul> |
||||
|
|
||||
|
<div class="tab-content"> |
||||
|
<div class="tab-pane active"> |
||||
|
{% block content %}{% endblock %} |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
{% endblock %} |
||||
@ -0,0 +1,53 @@ |
|||||
|
{% extends request.is_ajax|yesno:'nullcont.htm,ext.html' %} |
||||
|
{% load i18n %} |
||||
|
{% load 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> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
{% for log in logs %} |
||||
|
<tr> |
||||
|
<td class="btn-group btn-group-sm btn-group-justify"> |
||||
|
<button class="btn btn-default player-btn disabled"> |
||||
|
<span class="glyphicon glyphicon-play"></span> |
||||
|
<audio preload="metadata" src="{{ log.path_to_media }}/{{ log.calldate|date:"YmdHi" }}-{{ log.src }}-{{ log.dst }}.wav"></audio> |
||||
|
</button> |
||||
|
<a href="{{ log.path_to_media }}/{{ log.calldate|date:"YmdHi" }}-{{ log.src }}-{{ log.dst }}.wav" class="btn btn-default disabled" target="_blank"> |
||||
|
<span class="glyphicon glyphicon-download-alt"></span> |
||||
|
</a> |
||||
|
</td> |
||||
|
<td>{{ log.calldate|date:'d E Y, 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 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> |
||||
|
</div> |
||||
|
|
||||
|
{% include 'toolbar_page.html' with pag=logs %} |
||||
|
|
||||
|
{% endblock %} |
||||
@ -0,0 +1,57 @@ |
|||||
|
{% extends request.is_ajax|yesno:'nullcont.htm,ext.html' %} |
||||
|
{% load i18n %} |
||||
|
{% load 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 'Type' %}</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-sm"> |
||||
|
<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> |
||||
|
{% if vmail.userfield == 'request' %}{% trans 'Request' %} |
||||
|
{% elif vmail.userfield == 'report' %}{% trans 'Report' %} |
||||
|
{% else %}{{ vmail.userfield }}{% endif %} |
||||
|
</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="9">{% trans 'Calls was not found' %}</td> |
||||
|
</tr> |
||||
|
{% endfor %} |
||||
|
</tbody> |
||||
|
</table> |
||||
|
</div> |
||||
|
|
||||
|
{% include 'toolbar_page.html' with pag=vmessages %} |
||||
|
|
||||
|
{% endblock %} |
||||
@ -0,0 +1,20 @@ |
|||||
|
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" target="_blank">%s</a>' % (url, value) |
||||
|
return a |
||||
|
else: |
||||
|
return value |
||||
@ -0,0 +1,3 @@ |
|||||
|
from django.test import TestCase |
||||
|
|
||||
|
# Create your tests here. |
||||
@ -0,0 +1,9 @@ |
|||||
|
from django.conf.urls import url |
||||
|
from . import views |
||||
|
|
||||
|
|
||||
|
urlpatterns = [ |
||||
|
url(r'^$', views.home, name='home'), |
||||
|
url(r'^to_abon(?P<tel>\+?\d+)$', views.to_abon, name='to_abon'), |
||||
|
url(r'^voicemail$', views.vmail, name='vmail') |
||||
|
] |
||||
@ -0,0 +1,49 @@ |
|||||
|
from django.contrib.auth.decorators import login_required |
||||
|
from django.contrib import messages |
||||
|
from django.shortcuts import render, redirect |
||||
|
from django.utils.translation import ugettext_lazy as _ |
||||
|
|
||||
|
from abonapp.models import Abon |
||||
|
from mydefs import only_admins, pag_mn |
||||
|
from .models import AsteriskCDR |
||||
|
|
||||
|
|
||||
|
@login_required |
||||
|
@only_admins |
||||
|
def home(request): |
||||
|
logs = AsteriskCDR.objects.exclude(userfield='request').order_by('-calldate') |
||||
|
logs = pag_mn(request, logs) |
||||
|
title = _('Last calls') |
||||
|
return render(request, 'index.html', { |
||||
|
'logs': logs, |
||||
|
'title': title |
||||
|
}) |
||||
|
|
||||
|
|
||||
|
@login_required |
||||
|
@only_admins |
||||
|
def to_abon(request, tel): |
||||
|
abon = Abon.objects.filter(telephone=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, uid=abon.pk) |
||||
|
else: |
||||
|
return redirect('abonapp:group_list') |
||||
|
|
||||
|
|
||||
|
@login_required |
||||
|
@only_admins |
||||
|
def vmail(request): |
||||
|
title = _('Voice mail') |
||||
|
cdr = AsteriskCDR.objects.filter(userfield='request').order_by('-calldate') |
||||
|
cdr = pag_mn(request, cdr) |
||||
|
return render(request, 'vmail.html', { |
||||
|
'title': title, |
||||
|
'vmessages': cdr |
||||
|
}) |
||||
@ -0,0 +1,38 @@ |
|||||
|
import importlib |
||||
|
from netaddr import mac_unix, mac_eui48 |
||||
|
|
||||
|
|
||||
|
MAC_ADDR_REGEX = r'^([0-9A-Fa-f]{1,2}[:-]){5}([0-9A-Fa-f]{1,2})$' |
||||
|
|
||||
|
class mac_linux(mac_unix): |
||||
|
"""MAC format with zero-padded all upper-case hex and colon separated""" |
||||
|
word_fmt = '%x' |
||||
|
|
||||
|
|
||||
|
def default_dialect(eui_obj=None): |
||||
|
return mac_linux |
||||
|
|
||||
|
|
||||
|
def format_mac(eui_obj, dialect): |
||||
|
# Format a EUI instance as a string using the supplied dialect class, allowing custom string classes by |
||||
|
# passing directly or as a string, a la 'module.dialect_cls', where 'module' is the module and 'dialect_cls' |
||||
|
# is the class name of the custom dialect. The dialect must either be defined or imported by the module's __init__.py if |
||||
|
# the module is a package. |
||||
|
if not isinstance(dialect, mac_eui48): |
||||
|
if isinstance(dialect, str): |
||||
|
module, dialect_cls = dialect.split('.') |
||||
|
dialect = getattr(importlib.import_module(module), dialect_cls) |
||||
|
eui_obj.dialect = dialect |
||||
|
return str(eui_obj) |
||||
|
|
||||
|
|
||||
|
from pkg_resources import get_distribution, DistributionNotFound |
||||
|
|
||||
|
try: |
||||
|
_dist = get_distribution('django-macaddress') |
||||
|
except DistributionNotFound: |
||||
|
__version__ = 'Please install this project with setup.py' |
||||
|
else: |
||||
|
__version__ = _dist.version |
||||
|
VERSION = __version__ # synonym |
||||
|
default_app_config = 'abonapp.apps.AbonappConfig' |
||||
@ -1,32 +0,0 @@ |
|||||
#!/bin/env python3 |
|
||||
# coding=utf-8 |
|
||||
|
|
||||
import os |
|
||||
import MySQLdb |
|
||||
from json import dumps |
|
||||
|
|
||||
|
|
||||
if __name__ == "__main__": |
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djing.settings") |
|
||||
|
|
||||
db = MySQLdb.connect(host="localhost", user="root", passwd="ps", db="nodeny", charset='utf8') |
|
||||
cursor = db.cursor() |
|
||||
|
|
||||
result = dict() |
|
||||
|
|
||||
# выбираем абонентов |
|
||||
sql = r"SELECT location, descr FROM places WHERE location LIKE 'Сад_%'" |
|
||||
cursor.execute(sql) |
|
||||
places = list() |
|
||||
res = cursor.fetchone() |
|
||||
while res: |
|
||||
places.append({ |
|
||||
'loc': res[0], |
|
||||
'descr': res[1] |
|
||||
}) |
|
||||
res = cursor.fetchone() |
|
||||
|
|
||||
db.close() |
|
||||
f = open('../../places.json', 'w') |
|
||||
f.write(dumps(places, ensure_ascii=False).encode('utf8')) |
|
||||
f.close() |
|
||||
@ -1,92 +0,0 @@ |
|||||
#!/bin/env python3 |
|
||||
# coding=utf-8 |
|
||||
|
|
||||
import MySQLdb |
|
||||
from json import dumps, loads |
|
||||
|
|
||||
|
|
||||
def param_to_python(st): |
|
||||
st = st.replace('$VAR1 = ', '') |
|
||||
st = st.replace("'", '"') |
|
||||
st = st.replace(" =>", ':') |
|
||||
st = st.replace(";", '') |
|
||||
return loads(st) |
|
||||
|
|
||||
|
|
||||
def load_service(cursor, uid): |
|
||||
sql = "SELECT services.title, services.service_id, services.price, services.description, services.param " \ |
|
||||
"FROM services LEFT JOIN users_services ON " \ |
|
||||
"(users_services.service_id=services.service_id) WHERE users_services.uid=%d" % uid |
|
||||
cursor.execute(sql) |
|
||||
service_line = cursor.fetchone() |
|
||||
if service_line is not None: |
|
||||
service = { |
|
||||
'title': service_line[0], |
|
||||
'service_id': service_line[1], |
|
||||
'price': service_line[2], |
|
||||
'description': service_line[3], |
|
||||
'param': param_to_python(service_line[4]) |
|
||||
} |
|
||||
else: |
|
||||
service = None |
|
||||
return service |
|
||||
|
|
||||
|
|
||||
def load_users(cursor, grp_id): |
|
||||
# выбираем абонентов |
|
||||
sql = r"SELECT users.name, users.fio, data0._adr_telefon, dictionary.v AS street, data0._adr_house, data0._birthday, " \ |
|
||||
"users.grp, INET_NTOA(ip_pool.ip) AS ip, users.balance, AES_DECRYPT(users.passwd, 'Vu6saiZa') as decr_passwd, users.id, " \ |
|
||||
"mac_uid.device_mac, mac_uid.device_port, mac_uid.oneconnect " \ |
|
||||
"FROM users " \ |
|
||||
"LEFT JOIN data0 ON (data0.uid = users.id) LEFT JOIN dictionary ON (dictionary.k = data0._adr_street AND dictionary.type = 'street') " \ |
|
||||
"LEFT JOIN mac_uid ON (mac_uid.uid=users.id) " \ |
|
||||
"LEFT JOIN ip_pool ON (ip_pool.uid = users.id) WHERE users.grp = %d" % grp_id |
|
||||
cursor.execute(sql) |
|
||||
users = [{ |
|
||||
'name': res[0], |
|
||||
'fio': res[1], |
|
||||
'tel': res[2], |
|
||||
'street': str(res[3] or ''), |
|
||||
'house': str(res[4]), |
|
||||
'birth': res[5], |
|
||||
'grp': int(res[6]), |
|
||||
'ip': str(res[7] or ''), |
|
||||
'balance': float(res[8]), |
|
||||
'passw': res[9].decode("utf-8") if res[9] is not None else '', |
|
||||
'service': load_service(cursor, int(res[10])), |
|
||||
'opt82': { |
|
||||
'dev_mac': res[11], |
|
||||
'dev_port': res[12], |
|
||||
'oneconnect': res[13] |
|
||||
} |
|
||||
} for res in cursor.fetchall()] |
|
||||
return users |
|
||||
|
|
||||
|
|
||||
def load_groups(cursor): |
|
||||
# выбираем группы |
|
||||
sql = r'SELECT grp_id, grp_name FROM user_grp' |
|
||||
cursor.execute(sql) |
|
||||
groups = list() |
|
||||
for res in cursor.fetchall(): |
|
||||
users = load_users(cursor=cursor, grp_id=int(res[0])) |
|
||||
groups.append({ |
|
||||
'gid': int(res[0]), |
|
||||
'gname': res[1], |
|
||||
'users': users |
|
||||
}) |
|
||||
return groups |
|
||||
|
|
||||
|
|
||||
|
|
||||
if __name__ == "__main__": |
|
||||
db = MySQLdb.connect(host="127.0.0.1", user="user", passwd="password", db="db", charset='utf8') |
|
||||
cursor = db.cursor() |
|
||||
|
|
||||
result = dict() |
|
||||
|
|
||||
result = load_groups(cursor=cursor) |
|
||||
db.close() |
|
||||
f = open('dump.json', 'w') |
|
||||
f.write(dumps(result, ensure_ascii=False)) |
|
||||
f.close() |
|
||||
@ -1,45 +0,0 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
import telnetlib |
|
||||
from mydefs import ping |
|
||||
from socket import error |
|
||||
from multiprocessing import Process |
|
||||
|
|
||||
|
|
||||
# Пробуем настроить свичи через telnet на snmp |
|
||||
|
|
||||
|
|
||||
def cmd(ip): |
|
||||
tn = telnetlib.Telnet(ip) |
|
||||
tn.read_until("login: ") |
|
||||
tn.write("\n") |
|
||||
tn.read_until("Password: ") |
|
||||
tn.write("\n") |
|
||||
|
|
||||
tn.write("create snmp community ertNjuWr ReadWrite\n") |
|
||||
tn.write("save\n") |
|
||||
tn.write("save config\n") |
|
||||
tn.write("save config config_id 1\n") |
|
||||
|
|
||||
tn.write("log\n") |
|
||||
print((tn.read_all())) |
|
||||
tn.close() |
|
||||
|
|
||||
|
|
||||
def prc(ip): |
|
||||
try: |
|
||||
if ping(ip): |
|
||||
cmd(ip) |
|
||||
except error: |
|
||||
print(('Error connect to', ip)) |
|
||||
|
|
||||
|
|
||||
if __name__ == '__main__': |
|
||||
proc_list = list() |
|
||||
with open('swips.txt', 'r') as f: |
|
||||
for ln in f: |
|
||||
ip = ln.strip() |
|
||||
p = Process(target=prc, args=(ip,)) |
|
||||
p.start() |
|
||||
proc_list.append(p) |
|
||||
for proc in proc_list: |
|
||||
proc.join() |
|
||||
@ -1,29 +0,0 @@ |
|||||
#!/bin/env python3 |
|
||||
# coding=utf-8 |
|
||||
|
|
||||
import os |
|
||||
from json import load |
|
||||
import django |
|
||||
|
|
||||
|
|
||||
if __name__ == "__main__": |
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djing.settings") |
|
||||
django.setup() |
|
||||
from devapp.models import Device |
|
||||
|
|
||||
with open('../../places.json', 'r') as f: |
|
||||
dat = load(f) |
|
||||
|
|
||||
for dt in dat: |
|
||||
if dt['descr']: |
|
||||
dt['descr']=dt['descr'].replace('10.15.', '10.115.') |
|
||||
dt['loc']=dt['loc'].encode('utf8') |
|
||||
try: |
|
||||
dev = Device.objects.get(ip_address=dt['descr']) |
|
||||
except Device.DoesNotExist: |
|
||||
dev = Device( |
|
||||
ip_address=dt['descr'] |
|
||||
) |
|
||||
dev.comment=dt['loc'] |
|
||||
dev.save() |
|
||||
print((dt['descr'], dt['loc'], dev)) |
|
||||
@ -1,280 +0,0 @@ |
|||||
#!/bin/env python3 |
|
||||
# coding=utf-8 |
|
||||
|
|
||||
import os |
|
||||
from json import load |
|
||||
import django |
|
||||
from django.utils import timezone |
|
||||
from django.core.exceptions import ValidationError |
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djing.settings") |
|
||||
django.setup() |
|
||||
from abonapp.models import Abon, AbonGroup, AbonRawPassword, AbonStreet, AbonTariff, Opt82 |
|
||||
from ip_pool.models import IpPoolItem |
|
||||
from tariff_app.models import Tariff |
|
||||
|
|
||||
|
|
||||
class DumpService(object): |
|
||||
price = 0.0 |
|
||||
speedIn = 0.0 |
|
||||
speedOut = 0.0 |
|
||||
|
|
||||
def __init__(self, obj=None): |
|
||||
if obj is None: return |
|
||||
self.title = obj['title'] |
|
||||
self.price = obj['price'] |
|
||||
self.description = obj['description'] |
|
||||
self.speedIn = int(obj['param']['speed_in1']) / 1000000 |
|
||||
self.speedOut = int(obj['param']['speed_out1']) / 1000000 |
|
||||
|
|
||||
@staticmethod |
|
||||
def build_from_db(obj): |
|
||||
self = DumpService() |
|
||||
self.title = obj.title |
|
||||
self.price = obj.amount |
|
||||
self.description = obj.descr |
|
||||
self.speedIn = obj.speedIn |
|
||||
self.speedOut = obj.speedOut |
|
||||
return self |
|
||||
|
|
||||
def __eq__(self, other): |
|
||||
assert isinstance(other, DumpService) |
|
||||
print('DBG:', type(other.price), other.price, type(self.price), self.price) |
|
||||
r = self.price == other.price |
|
||||
r = r and self.speedIn == other.speedIn |
|
||||
r = r and self.speedOut == other.speedOut |
|
||||
return r |
|
||||
|
|
||||
def __ne__(self, other): |
|
||||
return not self.__eq__(other) |
|
||||
|
|
||||
def __str__(self): |
|
||||
return "%s; '%.2f', %f %f" % (self.title, self.price, self.speedIn, self.speedOut) |
|
||||
|
|
||||
|
|
||||
class DumpAbon(object): |
|
||||
|
|
||||
def __init__(self, obj=None): |
|
||||
if obj is None: return |
|
||||
self.name = obj['name'] |
|
||||
self.fio = obj['fio'] |
|
||||
self.tel = obj['tel'] |
|
||||
self.street = obj['street'] |
|
||||
self.house = obj['house'] |
|
||||
self.birth = obj['birth'] |
|
||||
self.grp = obj['grp'] |
|
||||
self.ip = obj['ip'] if obj['ip'] != '' else None |
|
||||
self.balance = obj['balance'] |
|
||||
self.passw = obj['passw'] |
|
||||
if obj['opt82']['dev_mac'] is not None and obj['opt82']['dev_port'] is not None: |
|
||||
self.opt82 = { |
|
||||
'dev_mac': obj['opt82']['dev_mac'], |
|
||||
'dev_port': obj['opt82']['dev_port'] |
|
||||
} |
|
||||
|
|
||||
if obj['service'] is not None: |
|
||||
self.service = DumpService(obj['service']) |
|
||||
else: |
|
||||
self.service = None |
|
||||
|
|
||||
@staticmethod |
|
||||
def build_from_django(obj): |
|
||||
assert isinstance(obj, Abon) |
|
||||
self = DumpAbon() |
|
||||
self.name = obj.username |
|
||||
self.fio = obj.fio |
|
||||
self.tel = obj.telephone |
|
||||
self.street = obj.street |
|
||||
self.house = obj.house |
|
||||
self.birth = obj.birth_day |
|
||||
if obj.group is None: |
|
||||
self.grp = None |
|
||||
else: |
|
||||
self.grp = obj.group.pk |
|
||||
if obj.ip_address is None: |
|
||||
self.ip = None |
|
||||
else: |
|
||||
self.ip = obj.ip_address |
|
||||
self.balance = obj.ballance |
|
||||
try: |
|
||||
raw_passw = AbonRawPassword.objects.get(account=obj) |
|
||||
except AbonRawPassword.DoesNotExist: |
|
||||
raw_passw = '' |
|
||||
self.passw = raw_passw |
|
||||
srv = obj.active_tariff() |
|
||||
if srv is not None: |
|
||||
self.service = DumpService.build_from_db(srv) |
|
||||
else: |
|
||||
self.service = None |
|
||||
if obj.opt82 is not None and obj.opt82.mac is not None and obj.opt82.port is not None: |
|
||||
self.opt82 = { |
|
||||
'dev_mac': obj.opt82.mac, |
|
||||
'dev_port': obj.opt82.port |
|
||||
} |
|
||||
return self |
|
||||
|
|
||||
def __eq__(self, other): |
|
||||
assert isinstance(other, DumpAbon) |
|
||||
r = self.name == other.name |
|
||||
r = r and self.name == other.name |
|
||||
r = r and self.fio == other.fio |
|
||||
r = r and self.tel == other.tel |
|
||||
r = r and self.street == other.street |
|
||||
r = r and self.house == other.house |
|
||||
r = r and self.birth == other.birth |
|
||||
r = r and self.grp == other.grp |
|
||||
r = r and self.ip == other.ip |
|
||||
r = r and self.balance == other.ballance |
|
||||
return r |
|
||||
|
|
||||
def __ne__(self, other): |
|
||||
return not self.__eq__(other) |
|
||||
|
|
||||
|
|
||||
def add_service_if_not_exist(service): |
|
||||
assert isinstance(service, DumpService) |
|
||||
try: |
|
||||
obj = Tariff.objects.get(speedIn=service.speedIn, speedOut=service.speedOut, amount=service.price) |
|
||||
except Tariff.DoesNotExist: |
|
||||
obj = Tariff.objects.create( |
|
||||
title=service.title, |
|
||||
descr=service.description, |
|
||||
speedIn=service.speedIn, |
|
||||
speedOut=service.speedOut, |
|
||||
amount=service.price, |
|
||||
calc_type='Dp' |
|
||||
) |
|
||||
return obj |
|
||||
|
|
||||
|
|
||||
def add_raw_password_if_not_exist(acc, raw_passw): |
|
||||
try: |
|
||||
psw = AbonRawPassword.objects.get(account=acc) |
|
||||
#if psw != raw_passw: |
|
||||
# psw.passw_text = raw_passw |
|
||||
# psw.save(update_fields=['passw_text']) |
|
||||
except AbonRawPassword.DoesNotExist: |
|
||||
psw = AbonRawPassword.objects.create(account=acc, passw_text=raw_passw) |
|
||||
return psw |
|
||||
|
|
||||
|
|
||||
def add_opt82_if_not_exist(mac, port): |
|
||||
print(mac, port) |
|
||||
try: |
|
||||
opt82 = Opt82.objects.get(mac=mac, port=port) |
|
||||
except Opt82.DoesNotExist: |
|
||||
opt82 = Opt82.objects.create(mac=mac, port=port) |
|
||||
return opt82 |
|
||||
|
|
||||
|
|
||||
def load_users(obj, group): |
|
||||
if len(obj) < 1: |
|
||||
return |
|
||||
for usr in obj: |
|
||||
# абонент из дампа |
|
||||
dump_abon = DumpAbon(usr) |
|
||||
# абонент из биллинга |
|
||||
print('\t', dump_abon.name, dump_abon.fio, dump_abon.ip) |
|
||||
try: |
|
||||
abon = Abon.objects.get(username=dump_abon.name) |
|
||||
bl_abon = DumpAbon.build_from_django(abon) |
|
||||
if bl_abon != dump_abon: |
|
||||
update_user(abon, dump_abon, group) |
|
||||
except Abon.DoesNotExist: |
|
||||
# добавляем абонента |
|
||||
abon = add_user(dump_abon, group) |
|
||||
if abon is None: |
|
||||
raise Exception("Чё за херня!? Не создался абонент") |
|
||||
|
|
||||
abon_service_from_dump = dump_abon.service |
|
||||
if abon_service_from_dump is None: |
|
||||
continue |
|
||||
abon_service = add_service_if_not_exist(abon_service_from_dump) |
|
||||
try: |
|
||||
AbonTariff.objects.get(abon=abon, tariff=abon_service) |
|
||||
except AbonTariff.DoesNotExist: |
|
||||
calc_obj = abon_service.get_calc_type()(abon_service) |
|
||||
AbonTariff.objects.create( |
|
||||
abon=abon, |
|
||||
tariff=abon_service, |
|
||||
time_start=timezone.now(), |
|
||||
deadline=calc_obj.calc_deadline() |
|
||||
) |
|
||||
try: |
|
||||
if hasattr(dump_abon, 'opt82'): |
|
||||
abon.opt82 = add_opt82_if_not_exist(dump_abon.opt82['dev_mac'], dump_abon.opt82['dev_port']) |
|
||||
abon.save(update_fields=['opt82']) |
|
||||
except ValidationError as e: |
|
||||
print('\t', e) |
|
||||
|
|
||||
|
|
||||
def add_user(obj, user_group): |
|
||||
assert isinstance(obj, DumpAbon) |
|
||||
street = None |
|
||||
ip = None |
|
||||
try: |
|
||||
if obj.ip is not None: |
|
||||
ip = IpPoolItem.objects.get(ip=obj.ip) |
|
||||
street = AbonStreet.objects.get(name=obj.street, group=user_group) |
|
||||
except IpPoolItem.DoesNotExist: |
|
||||
if obj.ip is not None: |
|
||||
ip = IpPoolItem.objects.create(ip=obj.ip) |
|
||||
except AbonStreet.DoesNotExist: |
|
||||
street = AbonStreet.objects.create(name=obj.street, group=user_group) |
|
||||
|
|
||||
abon = Abon() |
|
||||
abon.username = obj.name |
|
||||
abon.fio = obj.fio |
|
||||
abon.telephone = obj.tel |
|
||||
abon.street = street |
|
||||
abon.house = obj.house |
|
||||
abon.birth_day = obj.birth |
|
||||
abon.group = user_group |
|
||||
abon.ip_address = ip |
|
||||
abon.ballance = obj.balance |
|
||||
abon.set_password(obj.passw) |
|
||||
abon.save() |
|
||||
add_raw_password_if_not_exist(abon, obj.passw) |
|
||||
return abon |
|
||||
|
|
||||
|
|
||||
def update_user(db_abon, obj, user_group): |
|
||||
assert isinstance(obj, DumpAbon) |
|
||||
assert isinstance(db_abon, Abon) |
|
||||
street = None |
|
||||
ip = None |
|
||||
try: |
|
||||
if obj.ip is not None: |
|
||||
ip = IpPoolItem.objects.get(ip=obj.ip) |
|
||||
street = AbonStreet.objects.get(name=obj.street, group=user_group) |
|
||||
except IpPoolItem.DoesNotExist: |
|
||||
if obj.ip is not None: |
|
||||
ip = IpPoolItem.objects.create(ip=obj.ip) |
|
||||
except AbonStreet.DoesNotExist: |
|
||||
street = AbonStreet.objects.create(name=obj.street, group=user_group) |
|
||||
db_abon.fio = obj.fio |
|
||||
db_abon.telephone = obj.tel |
|
||||
db_abon.street = street |
|
||||
db_abon.house = obj.house |
|
||||
#db_abon.birth_day = datetime(obj.birth) |
|
||||
db_abon.group = user_group |
|
||||
db_abon.ip_address = ip |
|
||||
db_abon.ballance = obj.balance |
|
||||
db_abon.set_password(obj.passw) |
|
||||
db_abon.save() |
|
||||
add_raw_password_if_not_exist(db_abon, obj.passw) |
|
||||
|
|
||||
|
|
||||
if __name__ == "__main__": |
|
||||
|
|
||||
with open('dump.json', 'r') as f: |
|
||||
dat = load(f) |
|
||||
|
|
||||
for grp in dat: |
|
||||
try: |
|
||||
abgrp=AbonGroup.objects.get(title=grp['gname']) |
|
||||
except AbonGroup.DoesNotExist: |
|
||||
abgrp = AbonGroup.objects.create( |
|
||||
title=grp['gname'] |
|
||||
) |
|
||||
print(grp['gname']) |
|
||||
load_users(grp['users'], abgrp) |
|
||||
Some files were not shown because too many files changed in this diff
Write
Preview
Loading…
Cancel
Save
Reference in new issue