Browse Source

Merge branch 'master' into konica_tv

devel
Dmitry Novikov 5 years ago
parent
commit
9b3b0701d1
  1. 4
      abonapp/locale/ru/LC_MESSAGES/django.po
  2. 4
      abonapp/templates/abonapp/editAbon.html
  3. 4
      abonapp/views.py
  4. 1
      accounts_app/forms.py
  5. 2
      agent/netflow/netflow_collect.sh
  6. 6
      clientsideapp/views.py
  7. 33
      devapp/dev_types.py
  8. 2
      devapp/locale/ru/LC_MESSAGES/django.po
  9. 4
      devapp/templates/devapp/custom_dev_page/onu.html
  10. 4
      devapp/templates/devapp/custom_dev_page/onu_for_zte.html
  11. 2
      devapp/templates/devapp/devices.html
  12. 2
      devapp/views.py
  13. 2
      djing/__init__.py
  14. 10
      djing/settings.py
  15. 3
      djing/urls.py
  16. 0
      docsapp/__init__.py
  17. 5
      docsapp/apps.py
  18. 8
      docsapp/forms.py
  19. 71
      docsapp/locale/ru/LC_MESSAGES/django.po
  20. 27
      docsapp/migrations/0001_initial.py
  21. 0
      docsapp/migrations/__init__.py
  22. 24
      docsapp/models.py
  23. 14
      docsapp/templates/docsapp/documenttemplatemodel_confirm_delete.html
  24. 39
      docsapp/templates/docsapp/documenttemplatemodel_form.html
  25. 77
      docsapp/templates/docsapp/documenttemplatemodel_list.html
  26. 26
      docsapp/templates/docsapp/simple_list.html
  27. 14
      docsapp/urls.py
  28. 101
      docsapp/views.py
  29. 2
      gw_app/nas_managers/mod_mikrotik.py
  30. 85
      migrate2v2_dump.py
  31. 2
      periodic.py
  32. 33
      requirements.txt
  33. 1
      systemd_units/djing.timer
  34. 1
      systemd_units/djing_backup.timer
  35. 7
      systemd_units/webdav_backup.py
  36. 8
      tariff_app/custom_tariffs.py
  37. 6
      templates/base.html
  38. 2
      templates/custom_pages/footer.htm
  39. 2
      templates/custom_pages/main_page.htm
  40. 4
      templates/custom_pages/service.htm
  41. 2
      templates/custom_pages/service_bottom.htm

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

@ -1133,3 +1133,7 @@ msgstr "Выберите шлюз для абонента"
msgid "Are you sure you want to free ip user session?" msgid "Are you sure you want to free ip user session?"
msgstr "Вы уверены что хотите удалить ip абонента?" msgstr "Вы уверены что хотите удалить ip абонента?"
msgid "Document list"
msgstr "Документы"

4
abonapp/templates/abonapp/editAbon.html

@ -99,6 +99,10 @@
<span>{% trans 'Remove subscriber' %}</span> <span>{% trans 'Remove subscriber' %}</span>
</a> </a>
{% endif %} {% endif %}
<a href="{% url 'docsapp:simple_list' abon.username %}" class="btn btn-default btn-modal">
<span class="glyphicon glyphicon-print"></span> {% trans 'Document list' %}
</a>
</div> </div>
</div> </div>

4
abonapp/views.py

@ -776,7 +776,7 @@ def abon_ping(request, gid: int, uname):
@json_view @json_view
def set_auto_continue_service(request, gid: int, uname): def set_auto_continue_service(request, gid: int, uname):
checked = request.GET.get('checked') checked = request.GET.get('checked')
checked = True if checked == 'true' else False
checked = checked == 'true'
abon = get_object_or_404(models.Abon, username=uname) abon = get_object_or_404(models.Abon, username=uname)
abon.autoconnect_service = checked abon.autoconnect_service = checked
abon.save(update_fields=('autoconnect_service',)) abon.save(update_fields=('autoconnect_service',))
@ -845,7 +845,7 @@ def save_user_dev_port(request, gid: int, uname):
return redirect('abonapp:abon_home', gid, uname) return redirect('abonapp:abon_home', gid, uname)
user_port = lib.safe_int(request.POST.get('user_port')) user_port = lib.safe_int(request.POST.get('user_port'))
is_dynamic_ip = request.POST.get('is_dynamic_ip') is_dynamic_ip = request.POST.get('is_dynamic_ip')
is_dynamic_ip = True if is_dynamic_ip == 'on' else False
is_dynamic_ip = is_dynamic_ip == 'on'
try: try:
abon = models.Abon.objects.get(username=uname) abon = models.Abon.objects.get(username=uname)
if user_port == 0: if user_port == 0:

1
accounts_app/forms.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from guardian.forms import UserObjectPermissionsForm from guardian.forms import UserObjectPermissionsForm
from guardian.shortcuts import assign_perm, remove_perm from guardian.shortcuts import assign_perm, remove_perm
from django import forms from django import forms

2
agent/netflow/netflow_collect.sh

@ -15,7 +15,7 @@ spec.loader.exec_module(ls)
db = ls.DATABASES db = ls.DATABASES
ldb = db.get('default') ldb = db.get('default')
print('%s %s %s %s %d' % (ldb['NAME'], ldb['USER'], print('%s %s %s %s %d' % (ldb['NAME'], ldb['USER'],
ldb['PASSWORD'], ldb['HOST'], ldb['PORT']))"`
ldb['PASSWORD'], ldb['HOST'], ldb.get('PORT', 3306)))"`
if ! ping -c 1 ${mysql_host} &> /dev/null; then if ! ping -c 1 ${mysql_host} &> /dev/null; then
echo "Host ${mysql_host} is not accessible" echo "Host ${mysql_host} is not accessible"

6
clientsideapp/views.py

@ -17,7 +17,7 @@ from gw_app.nas_managers import NasFailedResult, NasNetworkError
@login_required @login_required
def home(request): def home(request):
num_active_tasks = Task.objects.filter( num_active_tasks = Task.objects.filter(
abon=request.user, state='S'
abon=request.user, state=0
).count() ).count()
return render(request, 'clientsideapp/index.html', { return render(request, 'clientsideapp/index.html', {
'num_active_tasks': num_active_tasks 'num_active_tasks': num_active_tasks
@ -38,7 +38,7 @@ def services(request):
abon = request.user abon = request.user
all_tarifs = Tariff.objects.get_tariffs_by_group( all_tarifs = Tariff.objects.get_tariffs_by_group(
abon.group.pk abon.group.pk
)# .filter(is_admin=False)
).filter(is_admin=False)
current_service = abon.active_tariff() current_service = abon.active_tariff()
except Abon.DoesNotExist: except Abon.DoesNotExist:
all_tarifs = None all_tarifs = None
@ -140,7 +140,7 @@ def task_history(request):
@json_view @json_view
def set_auto_continue_service(request): def set_auto_continue_service(request):
checked = request.GET.get('checked') checked = request.GET.get('checked')
checked = True if checked == 'true' else False
checked = checked == 'true'
abon = request.user abon = request.user
abon.autoconnect_service = checked abon.autoconnect_service = checked
abon.save(update_fields=('autoconnect_service',)) abon.save(update_fields=('autoconnect_service',))

33
devapp/dev_types.py

@ -113,7 +113,7 @@ class DLinkDevice(DevBase, SNMPBaseWorker):
uptimes = self.get_list('.1.3.6.1.2.1.2.2.1.9') uptimes = self.get_list('.1.3.6.1.2.1.2.2.1.9')
try: try:
for num in ints: for num in ints:
status = True if int(next(stats)) == 1 else False
status = int(next(stats)) == 1
yield DLinkPort( yield DLinkPort(
num=num, num=num,
name=next(nams), name=next(nams),
@ -187,7 +187,7 @@ class OLTDevice(DevBase, SNMPBaseWorker):
onu = ONUdev( onu = ONUdev(
num=n, num=n,
name=self.get_item('.1.3.6.1.2.1.2.2.1.2.%d' % n), name=self.get_item('.1.3.6.1.2.1.2.2.1.2.%d' % n),
status=True if status == '3' else False,
status=status == '3',
mac=self.get_item('.1.3.6.1.4.1.3320.101.10.1.1.3.%d' % n), mac=self.get_item('.1.3.6.1.4.1.3320.101.10.1.1.3.%d' % n),
speed=0, speed=0,
signal=signal / 10 if signal else '', signal=signal / 10 if signal else '',
@ -268,7 +268,7 @@ class OnuDevice(DevBase, SNMPBaseWorker):
distance = self.get_item('.1.3.6.1.4.1.3320.101.10.1.1.27.%d' % num) distance = self.get_item('.1.3.6.1.4.1.3320.101.10.1.1.27.%d' % num)
mac = self.get_item('.1.3.6.1.4.1.3320.101.10.1.1.3.%d' % num) mac = self.get_item('.1.3.6.1.4.1.3320.101.10.1.1.3.%d' % num)
if mac is not None: if mac is not None:
mac = ':'.join('%x' % ord(i) for i in mac)
mac = ':'.join('%x' % i for i in mac)
# uptime = self.get_item('.1.3.6.1.2.1.2.2.1.9.%d' % num) # uptime = self.get_item('.1.3.6.1.2.1.2.2.1.9.%d' % num)
if status is not None and status.isdigit(): if status is not None and status.isdigit():
return { return {
@ -276,7 +276,7 @@ class OnuDevice(DevBase, SNMPBaseWorker):
'signal': signal / 10 if signal else '', 'signal': signal / 10 if signal else '',
'name': self.get_item('.1.3.6.1.2.1.2.2.1.2.%d' % num), 'name': self.get_item('.1.3.6.1.2.1.2.2.1.2.%d' % num),
'mac': mac, 'mac': mac,
'distance': int(distance) / 10 if distance.isdigit() else 0
'distance': distance / 10 if distance else 0
} }
except EasySNMPTimeoutError as e: except EasySNMPTimeoutError as e:
return {'err': "%s: %s" % (_('ONU not connected'), e)} return {'err': "%s: %s" % (_('ONU not connected'), e)}
@ -391,27 +391,6 @@ class Olt_ZTE_C320(OLTDevice):
} for fiber_name, fiber_id in self.get_list_keyval('.1.3.6.1.4.1.3902.1012.3.13.1.1.1')) } for fiber_name, fiber_id in self.get_list_keyval('.1.3.6.1.4.1.3902.1012.3.13.1.1.1'))
return fibers return fibers
def get_ports_on_fiber(self, fiber_num: int) -> Iterable:
onu_types = self.get_list_keyval('.1.3.6.1.4.1.3902.1012.3.28.1.1.1.%d' % fiber_num)
onu_ports = self.get_list('.1.3.6.1.4.1.3902.1012.3.28.1.1.2.%d' % fiber_num)
onu_signals = safe_int(self.get_list('.1.3.6.1.4.1.3902.1012.3.50.12.1.1.10.%d' % fiber_num))
# Real sn in last 3 octets
onu_sns = self.get_list('.1.3.6.1.4.1.3902.1012.3.28.1.1.5.%d' % fiber_num)
onu_prefixs = self.get_list('.1.3.6.1.4.1.3902.1012.3.50.11.2.1.1.%d' % fiber_num)
onu_list = ({
'onu_type': onu_type_num[0],
'onu_port': onu_port,
'onu_signal': conv_zte_signal(onu_signal),
'onu_sn': onu_prefix + ''.join('%.2X' % ord(i) for i in onu_sn[-4:]), # Real sn in last 4 octets,
'snmp_extra': "%d.%d" % (fiber_num, safe_int(onu_type_num[1])),
} for onu_type_num, onu_port, onu_signal, onu_sn, onu_prefix in zip(
onu_types, onu_ports, onu_signals, onu_sns, onu_prefixs
))
return onu_list
def get_units_unregistered(self, fiber_num: int) -> Iterable: def get_units_unregistered(self, fiber_num: int) -> Iterable:
sn_num_list = self.get_list_keyval('.1.3.6.1.4.1.3902.1012.3.13.3.1.2.%d' % fiber_num) sn_num_list = self.get_list_keyval('.1.3.6.1.4.1.3902.1012.3.13.3.1.2.%d' % fiber_num)
firmware_ver = self.get_list('.1.3.6.1.4.1.3902.1012.3.13.3.1.11.%d' % fiber_num) firmware_ver = self.get_list('.1.3.6.1.4.1.3902.1012.3.13.3.1.11.%d' % fiber_num)
@ -596,9 +575,9 @@ class HuaweiSwitch(EltexSwitch):
n = int(n) n = int(n)
speed = self.get_item('.1.3.6.1.2.1.2.2.1.5.%d' % n) speed = self.get_item('.1.3.6.1.2.1.2.2.1.5.%d' % n)
oper_status = safe_int(self.get_item('.1.3.6.1.2.1.2.2.1.7.%d' % n)) oper_status = safe_int(self.get_item('.1.3.6.1.2.1.2.2.1.7.%d' % n))
oper_status = True if oper_status == 1 else False
oper_status = oper_status == 1
link_status = safe_int(self.get_item('.1.3.6.1.2.1.2.2.1.8.%d' % n)) link_status = safe_int(self.get_item('.1.3.6.1.2.1.2.2.1.8.%d' % n))
link_status = True if link_status == 1 else False
link_status = link_status == 1
ep = EltexPort( ep = EltexPort(
self, self,
num=i+1, num=i+1,

2
devapp/locale/ru/LC_MESSAGES/django.po

@ -484,7 +484,7 @@ msgid "Are you sure you want to delete device?"
msgstr "Вы уверены что хотите удалить устройство?" msgstr "Вы уверены что хотите удалить устройство?"
#: templates/devapp/devices.html:83 templates/devapp/devices_null_group.html:65 #: templates/devapp/devices.html:83 templates/devapp/devices_null_group.html:65
msgid "Devices does not found"
msgid "Devices not found"
msgstr "Нет созданных устройств" msgstr "Нет созданных устройств"
#: templates/devapp/devices.html:83 templates/devapp/devices.html:93 #: templates/devapp/devices.html:83 templates/devapp/devices.html:93

4
devapp/templates/devapp/custom_dev_page/onu.html

@ -59,9 +59,9 @@
{% else %} {% else %}
<div class="media"> <div class="media">
<div class="media-left font-extra-large"> <div class="media-left font-extra-large">
{% if onu_details.status == '3' %}
{% if onu_details.status == 3 %}
<span class="media-object glyphicon glyphicon-ok-sign text-success"></span> <span class="media-object glyphicon glyphicon-ok-sign text-success"></span>
{% elif onu_details.status == '2' %}
{% elif onu_details.status == 2 %}
<span class="media-object glyphicon glyphicon-remove-sign text-danger"></span> <span class="media-object glyphicon glyphicon-remove-sign text-danger"></span>
{% else %} {% else %}
<span class="media-object glyphicon glyphicon-question-sign"></span> <span class="media-object glyphicon glyphicon-question-sign"></span>

4
devapp/templates/devapp/custom_dev_page/onu_for_zte.html

@ -60,9 +60,9 @@
{% else %} {% else %}
<div class="media"> <div class="media">
<div class="media-left font-extra-large"> <div class="media-left font-extra-large">
{% if onu_details.status == '1' %}
{% if onu_details.status == 1 %}
<span class="media-object glyphicon glyphicon-ok-sign text-success"></span> <span class="media-object glyphicon glyphicon-ok-sign text-success"></span>
{% elif onu_details.status == '2' %}
{% elif onu_details.status == 2 %}
<span class="media-object glyphicon glyphicon-remove-sign text-danger"></span> <span class="media-object glyphicon glyphicon-remove-sign text-danger"></span>
{% else %} {% else %}
<span class="media-object glyphicon glyphicon-question-sign"></span> <span class="media-object glyphicon glyphicon-question-sign"></span>

2
devapp/templates/devapp/devices.html

@ -82,7 +82,7 @@
</tr> </tr>
{% empty %} {% empty %}
<tr> <tr>
<td colspan="6">{% trans 'Devices does not found' %}. <a href="{% url 'devapp:add' group.pk %}">{% trans 'Create' %}</a></td>
<td colspan="6">{% trans 'Devices not found' %}. <a href="{% url 'devapp:add' group.pk %}">{% trans 'Create' %}</a></td>
</tr> </tr>
{% endfor %} {% endfor %}
{% endwith %} {% endwith %}

2
devapp/views.py

@ -681,7 +681,7 @@ def fix_onu(request):
}) })
for srcmac, snmpnum in ports: for srcmac, snmpnum in ports:
# convert bytes mac address to str presentation mac address # convert bytes mac address to str presentation mac address
real_mac = ':'.join('%x' % ord(i) for i in srcmac)
real_mac = ':'.join('%x' % i for i in srcmac)
if mac == real_mac: if mac == real_mac:
onu.snmp_extra = str(snmpnum) onu.snmp_extra = str(snmpnum)
onu.save(update_fields=('snmp_extra',)) onu.save(update_fields=('snmp_extra',))

2
djing/__init__.py

@ -57,7 +57,7 @@ default_app_config = 'abonapp.apps.AbonappConfig'
def ping(ip_addr: str, count=1): def ping(ip_addr: str, count=1):
if re.match(IP_ADDR_REGEX, ip_addr): if re.match(IP_ADDR_REGEX, ip_addr):
response = os.system("`which ping` -4Anq -c%d -W1 %s > /dev/null" % (count, ip_addr)) response = os.system("`which ping` -4Anq -c%d -W1 %s > /dev/null" % (count, ip_addr))
return True if response == 0 else False
return response == 0
else: else:
return False return False

10
djing/settings.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*
import os import os
try: try:
@ -43,6 +42,10 @@ INSTALLED_APPS = [
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'encrypted_model_fields', 'encrypted_model_fields',
'django_cleanup.apps.CleanupConfig', 'django_cleanup.apps.CleanupConfig',
'guardian',
'pinax_theme_bootstrap',
'bootstrapform',
'bootstrap3',
'ip_pool', 'ip_pool',
'accounts_app', 'accounts_app',
'gw_app', 'gw_app',
@ -59,10 +62,7 @@ INSTALLED_APPS = [
'msg_app', 'msg_app',
'group_app', 'group_app',
'new_customers', 'new_customers',
'guardian',
'pinax_theme_bootstrap',
'bootstrapform',
'bootstrap3'
'docsapp'
] ]
if DEBUG: if DEBUG:

3
djing/urls.py

@ -20,7 +20,8 @@ urlpatterns = [
path('messenger/', include('messenger.urls', namespace='messenger')), path('messenger/', include('messenger.urls', namespace='messenger')),
path('gw/', include('gw_app.urls', namespace='gw_app')), path('gw/', include('gw_app.urls', namespace='gw_app')),
path('new_customers/', include('new_customers.urls', namespace='new_customers')), path('new_customers/', include('new_customers.urls', namespace='new_customers')),
path('fin/', include('finapp.urls', namespace='finapp'))
path('fin/', include('finapp.urls', namespace='finapp')),
path('docs/', include('docsapp.urls', namespace='docsapp'))
# Switch language # Switch language
#path(r'i18n/', include('django.conf.urls.i18n')), #path(r'i18n/', include('django.conf.urls.i18n')),

0
docsapp/__init__.py

5
docsapp/apps.py

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

8
docsapp/forms.py

@ -0,0 +1,8 @@
from django import forms
from docsapp.models import DocumentTemplateModel
class DocumentTemplateModelForm(forms.ModelForm):
class Meta:
model = DocumentTemplateModel
fields = '__all__'

71
docsapp/locale/ru/LC_MESSAGES/django.po

@ -0,0 +1,71 @@
# 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, 2019.
#
#, fuzzy
msgid ""
msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-09-12 13:57+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Dmitry Novikov nerosketch@gmail.com\n"
"Language: ru\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:8 templates/docsapp/documenttemplatemodel_list.html:25
msgid "Title"
msgstr "Название"
#: models.py:10
msgid "File docx template"
msgstr "Файл шаблон docx"
#: templates/docsapp/documenttemplatemodel_confirm_delete.html:9
msgid "Remove document"
msgstr "Удалить документ"
#: templates/docsapp/documenttemplatemodel_confirm_delete.html:13
msgid "Are you sure you want to delete this document?"
msgstr "Вы уверены что хотите удалить документ?"
#: templates/docsapp/documenttemplatemodel_form.html:19
msgid "Change document"
msgstr "Изменить документ"
#: templates/docsapp/documenttemplatemodel_form.html:21
#: templates/docsapp/documenttemplatemodel_list.html:58
#: templates/docsapp/documenttemplatemodel_list.html:69
msgid "Add document"
msgstr "Добавить документ"
#: templates/docsapp/documenttemplatemodel_form.html:30
msgid "Save"
msgstr "Сохранить"
#: templates/docsapp/documenttemplatemodel_form.html:34
msgid "Back"
msgstr "Назад"
#: templates/docsapp/documenttemplatemodel_list.html:5
#: templates/docsapp/documenttemplatemodel_list.html:11
#: templates/docsapp/documenttemplatemodel_list.html:16
msgid "Documents"
msgstr "Документы"
#: templates/docsapp/documenttemplatemodel_list.html:26
msgid "File"
msgstr "Файл"
#: templates/docsapp/documenttemplatemodel_list.html:27
msgid "Document type"
msgstr "Тип документа"
#: templates/docsapp/documenttemplatemodel_list.html:57
msgid "Documents not found"
msgstr "Документы не найдены"

27
docsapp/migrations/0001_initial.py

@ -0,0 +1,27 @@
# Generated by Django 2.2.4 on 2019-09-12 12:52
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='DocumentTemplateModel',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=80, verbose_name='Title', unique=True)),
('doc_template', models.FileField(upload_to='word_docs', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=('docx',))], verbose_name='File docx template')),
],
options={
'db_table': 'documents',
'ordering': ('title',),
},
),
]

0
docsapp/migrations/__init__.py

24
docsapp/models.py

@ -0,0 +1,24 @@
from django.shortcuts import resolve_url
from django.utils.translation import gettext_lazy as _
from django.core.validators import FileExtensionValidator
from django.db import models
from abonapp.models import Abon
class DocumentTemplateModel(models.Model):
title = models.CharField(_('Title'), max_length=80, unique=True)
doc_template = models.FileField(
_('File docx template'), upload_to='word_docs',
validators=[FileExtensionValidator(allowed_extensions=('docx',))]
)
def get_absolute_url(self):
return resolve_url('docsapp:doc_edit', pk=self.pk)
def __str__(self):
return self.title
class Meta:
db_table = 'documents'
ordering = ('title',)

14
docsapp/templates/docsapp/documenttemplatemodel_confirm_delete.html

@ -0,0 +1,14 @@
{% extends 'base_delete_modal.html' %}
{% load i18n %}
{% block modal_form_url %}
{% url 'docsapp:doc_del' object.pk %}
{% endblock %}
{% block modal_form_title %}
{% trans 'Remove document' %}
{% endblock %}
{% block modal_form_text %}
<h4>{% trans 'Are you sure you want to delete this document?' %}</h4>
{% endblock %}

39
docsapp/templates/docsapp/documenttemplatemodel_form.html

@ -0,0 +1,39 @@
{% extends request.is_ajax|yesno:'bajax.html,base.html' %}
{% load i18n bootstrap3 %}
{% block main %}
{% if object %}
{% url 'docsapp:doc_edit' object.pk as objurl %}
{% else %}
{% url 'docsapp:doc_add' as objurl %}
{% endif %}
<form action="{{ objurl }}" method="post" enctype="multipart/form-data">{% 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-exclamation-sign"></span>
{% if object %}
{% trans 'Change document' %}
{% else %}
{% trans 'Add document' %}
{% endif %}
</h4>
</div>
<div class="modal-body">
{% bootstrap_form form %}
<div class="btn-group btn-group-sm">
{% bootstrap_button _('Save') button_type="submit" button_class="btn-primary" icon="save" %}
{% if not request.is_ajax %}
{% url 'docsapp:docs_list' as backurl %}
{% bootstrap_button _('Back') button_type="link" href=backurl icon="fast-backward" %}
{% endif %}
</div>
</div>
</form>
{% endblock %}

77
docsapp/templates/docsapp/documenttemplatemodel_list.html

@ -0,0 +1,77 @@
{% extends request.is_ajax|yesno:'bajax.html,base.html' %}
{% load i18n %}
{% block title %}
{% trans 'Documents' %}
{% endblock %}
{% block breadcrumb %}
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li class="active">{% trans 'Documents' %}</li>
</ol>
{% endblock %}
{% block page-header %}
{% trans 'Documents' %}
{% endblock %}
{% block main %}
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr>
<th>.</th>
<th class="col-md-2">{% trans 'Title' %}</th>
<th class="col-md-4">{% trans 'File' %}</th>
<th class="col-md-3">{% trans 'Document type' %}</th>
<th>#</th>
</tr>
</thead>
<tbody>
{% with can_del_doc=perms.docsapp.delete_documenttemplatemodel can_ch_doc=perms.docsapp.change_documenttemplatemodel %}
{% for doc in object_list %}
<tr>
<td>{{ doc.id }}</td>
<td>{{ doc.title }}</td>
<td>{{ doc.doc_template }}</td>
<td>DocX</td>
<td class="btn-group btn-group-xs btn-group-justified">
{% if can_del_doc %}
<a href="{% url 'docsapp:doc_del' doc.pk %}" class="btn btn-danger btn-modal">
<span class="glyphicon glyphicon-remove"></span>
</a>
{% endif %}
{% if can_ch_doc %}
<a href="{% url 'docsapp:doc_edit' doc.id %}" class="btn btn-default btn-modal">
<span class="glyphicon glyphicon-edit"></span>
</a>
{% endif %}
</td>
</tr>
{% empty %}
<tr>
<td colspan="6">
{% trans 'Documents not found' %}.
<a href="{% url 'docsapp:doc_add' %}" class="btn-modal">{% trans 'Add document' %}</a>
</td>
</tr>
{% endfor %}
{% endwith %}
</tbody>
<tfoot>
<tr>
<td colspan="6">
<a href="{% url 'docsapp:doc_add' %}" class="btn btn-success btn-sm btn-modal">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add document' %}
</a>
</td>
</tr>
</tfoot>
</table>
</div>
{% endblock %}

26
docsapp/templates/docsapp/simple_list.html

@ -0,0 +1,26 @@
{% load i18n %}
<div class="modal-header primary">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">{% trans 'Documents' %}</h4>
</div>
<div class="modal-body">
<div class="panel panel-default">
<div class="panel-body">
<ul class="list-group">
{% for obj in object_list %}
<li class="list-group-item">
<b>{{ obj.title }}</b>
<a href="{% url 'docsapp:doc_render' obj.pk account_name %}" class="btn btn-default">
<span class="glyphicon glyphicon-print"></span> {% trans 'Render document' %}
</a>
</li>
{% empty %}
{% trans 'Documents not found' %}
{% endfor %}
</ul>
</div>
</div>
</div>

14
docsapp/urls.py

@ -0,0 +1,14 @@
from django.urls import path
from docsapp import views
app_name = 'docsapp'
urlpatterns = [
path('', views.DocumentsListView.as_view(), name='docs_list'),
path('add/', views.DocumentCreateView.as_view(), name='doc_add'),
path('<int:pk>/', views.DocumentUpdateView.as_view(), name='doc_edit'),
path('<int:pk>/del/', views.DocumentDeleteView.as_view(), name='doc_del'),
path('<int:pk>/<slug:uname>/render/', views.RenderDocument.as_view(), name='doc_render'),
path('<slug:account_name>/simple_list/', views.SimpleListView.as_view(), name='simple_list'),
]

101
docsapp/views.py

@ -0,0 +1,101 @@
from io import BytesIO
from django.contrib import messages
from django.utils.datetime_safe import datetime
from django.utils.translation import gettext_lazy as _
from django.views.generic import UpdateView, DeleteView, CreateView, DetailView, ListView
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.core.exceptions import ValidationError
from django.http import HttpResponse
from django.shortcuts import redirect, get_object_or_404
from django.urls import reverse_lazy
from docxtpl import DocxTemplate
from docx.opc.constants import CONTENT_TYPE
from jinja2.exceptions import UndefinedError, TemplateSyntaxError
from abonapp.models import Abon
from djing.global_base_views import OrderedFilteredList
from djing.lib.mixins import LoginAdminMixin, LoginAdminPermissionMixin
from docsapp.models import DocumentTemplateModel
from docsapp.forms import DocumentTemplateModelForm
class DocumentsListView(LoginAdminMixin, OrderedFilteredList):
model = DocumentTemplateModel
class SimpleListView(LoginAdminMixin, ListView):
template_name = 'docsapp/simple_list.html'
model = DocumentTemplateModel
def get_context_data(self, **kwargs):
kwargs.update({
'account_name': self.kwargs.get('account_name')
})
return super().get_context_data(**kwargs)
class DocumentUpdateView(LoginAdminPermissionMixin, UpdateView):
permission_required = 'docsapp.change_documenttemplatemodel'
model = DocumentTemplateModel
form_class = DocumentTemplateModelForm
class DocumentDeleteView(LoginAdminPermissionMixin, DeleteView):
permission_required = 'docsapp.delete_documenttemplatemodel'
model = DocumentTemplateModel
success_url = reverse_lazy('docsapp:docs_list')
class DocumentCreateView(LoginAdminMixin, PermissionRequiredMixin, CreateView):
model = DocumentTemplateModel
form_class = DocumentTemplateModelForm
permission_required = 'docsapp.add_documenttemplatemodel'
class RenderDocument(LoginAdminPermissionMixin, DetailView):
model = DocumentTemplateModel
permission_required = 'docsapp.view_documenttemplatemodel'
context_object_name = 'document'
extra_context = {
'date': datetime.now()
}
def get(self, request, *args, **kwargs):
obj = self.get_object()
self.object = obj
acc = get_object_or_404(Abon, username=self.kwargs.get('uname'))
try:
doc = DocxTemplate(
obj.doc_template.path
)
context = self.get_context_data(object=obj)
context.update(self.get_context_account(acc))
doc.render(context)
destination_document_file = BytesIO()
doc.get_docx().save(destination_document_file)
resp = HttpResponse(
destination_document_file.getvalue(),
content_type=CONTENT_TYPE.WML_DOCUMENT
)
resp['Content-Disposition'] = 'attachment; filename="document.docx"'
return resp
except (UndefinedError, ValidationError, TemplateSyntaxError) as e:
messages.error(request, str(e))
return redirect('docsapp:docs_list')
def get_context_account(self, account):
if not isinstance(account, Abon):
raise ValidationError(message=_('Account required and must be Abon'))
bp = '_' * 20
return {
'account': account,
'passport': getattr(account, 'passportinfo', {
'series': bp,
'number': bp,
'distributor': bp,
'date_of_acceptance': bp
})
}

2
gw_app/nas_managers/mod_mikrotik.py

@ -235,7 +235,7 @@ class MikrotikTransmitter(core.BaseTransmitter, ApiRos,
name = info.get('=name') name = info.get('=name')
disabled = info.get('=disabled', False) disabled = info.get('=disabled', False)
if disabled is not None: if disabled is not None:
disabled = True if disabled == 'true' else False
disabled = disabled == 'true'
if target and name: if target and name:
# target may be '192.168.0.3/32,192.168.0.2/32' # target may be '192.168.0.3/32,192.168.0.2/32'
net = target.split(',')[0] net = target.split(',')[0]

85
migrate2v2_dump.py

@ -54,7 +54,7 @@ class BatchSaveStreamList(list):
# image fields # image fields
elif isinstance(field, ImageField): elif isinstance(field, ImageField):
val = getattr(obj, field.name) val = getattr(obj, field.name)
return getattr(val, 'url') if val else None
return getattr(val, 'name') if val else None
# mac address validated by netaddr.EUI # mac address validated by netaddr.EUI
elif isinstance(field, MACAddressField): elif isinstance(field, MACAddressField):
@ -84,10 +84,14 @@ class BatchSaveStreamList(list):
return 1 return 1
def batch_save(fname, *args, **kwargs):
def batch_save(app_label: str, fname: str, *args, **kwargs):
sa = BatchSaveStreamList(*args, **kwargs) sa = BatchSaveStreamList(*args, **kwargs)
print(fname)
with open(fname, 'w') as f:
fixt_dir = os.path.join('fixtures', app_label, 'fixtures')
if not os.path.isdir(fixt_dir):
os.makedirs(fixt_dir, mode=0o750)
full_path = os.path.join(fixt_dir, fname)
print(full_path)
with open(full_path, 'w') as f:
dump(sa, f, ensure_ascii=False, indent=2, cls=DjangoJSONEncoder) dump(sa, f, ensure_ascii=False, indent=2, cls=DjangoJSONEncoder)
@ -96,14 +100,15 @@ def batch_save(fname, *args, **kwargs):
def dump_groups(): def dump_groups():
from group_app.models import Group from group_app.models import Group
batch_save("groups.json", Group.objects.all(), 'groupapp.group')
batch_save(app_label='groupapp', fname="groups.json", model_queryset=Group.objects.all(), model_name='groupapp.group')
def dump_accounts(): def dump_accounts():
from accounts_app.models import UserProfile, BaseAccount, UserProfileLog from accounts_app.models import UserProfile, BaseAccount, UserProfileLog
batch_save('accounts_baseaccount.json', BaseAccount.objects.exclude(username='AnonymousUser'), 'profiles.baseaccount',
app_label = 'profiles'
batch_save(app_label=app_label, fname='accounts_baseaccount.json', model_queryset=BaseAccount.objects.exclude(username='AnonymousUser'), model_name='profiles.baseaccount',
except_fields=['groups', 'user_permissions']) except_fields=['groups', 'user_permissions'])
batch_save('accounts_userprofile.json', UserProfile.objects.exclude(username='AnonymousUser'), 'profiles.userprofile',
batch_save(app_label=app_label, fname='accounts_userprofile.json', model_queryset=UserProfile.objects.exclude(username='AnonymousUser'), model_name='profiles.userprofile',
except_fields=['groups', 'user_permissions']) except_fields=['groups', 'user_permissions'])
do_type_map = { do_type_map = {
'cusr': 1, 'dusr': 2, 'cusr': 1, 'dusr': 2,
@ -111,7 +116,7 @@ def dump_accounts():
'cnas': 5, 'dnas': 6, 'cnas': 5, 'dnas': 6,
'csrv': 7, 'dsrv': 8 'csrv': 7, 'dsrv': 8
} }
batch_save('accounts_userprofilelog.json', UserProfileLog.objects.all(), 'profiles.userprofilelog',
batch_save(app_label=app_label, fname='accounts_userprofilelog.json', model_queryset=UserProfileLog.objects.all(), model_name='profiles.userprofilelog',
except_fields=['meta_info'], except_fields=['meta_info'],
choice_list_map={ choice_list_map={
'do_type': do_type_map 'do_type': do_type_map
@ -120,15 +125,17 @@ def dump_accounts():
def dump_messenger(): def dump_messenger():
from messenger.models import Messenger, ViberMessenger, ViberMessage, ViberSubscriber from messenger.models import Messenger, ViberMessenger, ViberMessage, ViberSubscriber
batch_save("messenger.json", Messenger.objects.all(), 'messenger.messenger')
batch_save("vibermessenger.json", ViberMessenger.objects.all(), 'messenger.vibermessenger')
batch_save("vibermessage.json", ViberMessage.objects.all(), 'messenger.vibermessage')
batch_save("vibersubscriber.json", ViberSubscriber.objects.all(), 'messenger.vibersubscriber')
app_label = 'messenger'
batch_save(app_label, "messenger.json", Messenger.objects.all(), 'messenger.messenger')
batch_save(app_label, "vibermessenger.json", ViberMessenger.objects.all(), 'messenger.vibermessenger')
batch_save(app_label, "vibermessage.json", ViberMessage.objects.all(), 'messenger.vibermessage')
batch_save(app_label, "vibersubscriber.json", ViberSubscriber.objects.all(), 'messenger.vibersubscriber')
def dump_services(): def dump_services():
from tariff_app.models import Tariff, PeriodicPay from tariff_app.models import Tariff, PeriodicPay
batch_save("services.json", Tariff.objects.all(), 'services.service', field_name_map={
app_label = 'services'
batch_save(app_label, "services.json", Tariff.objects.all(), 'services.service', field_name_map={
'speedIn': 'speed_in', 'speedIn': 'speed_in',
'speedOut': 'speed_out', 'speedOut': 'speed_out',
'amount': 'cost' 'amount': 'cost'
@ -140,7 +147,7 @@ def dump_services():
'Dl': 3 'Dl': 3
} }
}) })
batch_save("services_periodicpay.json", PeriodicPay.objects.all(), 'services.periodicpay', choice_list_map={
batch_save(app_label, "services_periodicpay.json", PeriodicPay.objects.all(), 'services.periodicpay', choice_list_map={
'calc_type': { 'calc_type': {
'df': 0, 'df': 0,
'cs': 1 'cs': 1
@ -150,7 +157,8 @@ def dump_services():
def dump_gateways(): def dump_gateways():
from gw_app.models import NASModel from gw_app.models import NASModel
batch_save("gateways.json", NASModel.objects.all(), 'gateways.gateway', field_name_map={
app_label = 'gateways'
batch_save(app_label, "gateways.json", NASModel.objects.all(), 'gateways.gateway', field_name_map={
'nas_type': 'gw_type', 'nas_type': 'gw_type',
'default': 'is_default' 'default': 'is_default'
}, choice_list_map={ }, choice_list_map={
@ -162,7 +170,8 @@ def dump_gateways():
def dump_devices(): def dump_devices():
from devapp.models import Device, Port from devapp.models import Device, Port
batch_save("devices.json", Device.objects.all(), 'devices.device', field_name_map={
app_label = 'devices'
batch_save(app_label, "devices.json", Device.objects.all(), 'devices.device', field_name_map={
'devtype': 'dev_type' 'devtype': 'dev_type'
}, choice_list_map={ }, choice_list_map={
'devtype': { 'devtype': {
@ -178,7 +187,7 @@ def dump_devices():
'dwn': 3 'dwn': 3
} }
}) })
batch_save('devices_port.json', Port.objects.all(), 'devices.port')
batch_save(app_label, 'devices_port.json', Port.objects.all(), 'devices.port')
def dump_customers(): def dump_customers():
@ -187,41 +196,43 @@ def dump_customers():
PassportInfo, InvoiceForPayment, AbonRawPassword, PassportInfo, InvoiceForPayment, AbonRawPassword,
AdditionalTelephone, PeriodicPayForId AdditionalTelephone, PeriodicPayForId
) )
batch_save('customer.json', Abon.objects.exclude(username='AnonymousUser'), 'customers.customer', field_name_map={
app_label = 'customers'
batch_save(app_label, 'customer.json', Abon.objects.exclude(username='AnonymousUser'), 'customers.customer', field_name_map={
'current_tariff': 'current_service', 'current_tariff': 'current_service',
'ballance': 'balance', 'ballance': 'balance',
'nas': 'gateway', 'nas': 'gateway',
'autoconnect_service': 'auto_renewal_service', 'autoconnect_service': 'auto_renewal_service',
'last_connected_tariff': 'last_connected_service' 'last_connected_tariff': 'last_connected_service'
}, except_fields=['groups', 'user_permissions']) }, except_fields=['groups', 'user_permissions'])
batch_save('customers_log.json', AbonLog.objects.all(), 'customers.customerlog', field_name_map={
batch_save(app_label, 'customers_log.json', AbonLog.objects.all(), 'customers.customerlog', field_name_map={
'abon': 'customer', 'abon': 'customer',
'amount': 'cost' 'amount': 'cost'
}) })
batch_save('customers_service.json', AbonTariff.objects.all(), 'customers.customerservice', field_name_map={
batch_save(app_label, 'customers_service.json', AbonTariff.objects.all(), 'customers.customerservice', field_name_map={
'tariff': 'service', 'tariff': 'service',
'time_start': 'start_time' 'time_start': 'start_time'
}) })
batch_save('customers_street.json', AbonStreet.objects.all(), 'customers.customerstreet')
batch_save('customers_passport.json', PassportInfo.objects.all(), 'customers.passportinfo', field_name_map={
batch_save(app_label, 'customers_street.json', AbonStreet.objects.all(), 'customers.customerstreet')
batch_save(app_label, 'customers_passport.json', PassportInfo.objects.all(), 'customers.passportinfo', field_name_map={
'abon': 'customer' 'abon': 'customer'
}) })
batch_save('customers_inv.json', InvoiceForPayment.objects.all(), 'customers.invoiceforpayment', field_name_map={
batch_save(app_label, 'customers_inv.json', InvoiceForPayment.objects.all(), 'customers.invoiceforpayment', field_name_map={
'abon': 'customer', 'abon': 'customer',
'amount': 'cost' 'amount': 'cost'
}) })
batch_save('customers_passw.json', AbonRawPassword.objects.all(), 'customers.customerrawpassword', field_name_map={
batch_save(app_label, 'customers_passw.json', AbonRawPassword.objects.all(), 'customers.customerrawpassword', field_name_map={
'account': 'customer' 'account': 'customer'
}) })
batch_save('customers_tels.json', AdditionalTelephone.objects.all(), 'customers.additionaltelephone', field_name_map={
batch_save(app_label, 'customers_tels.json', AdditionalTelephone.objects.all(), 'customers.additionaltelephone', field_name_map={
'abon': 'customer' 'abon': 'customer'
}) })
batch_save('customers_tels.json', PeriodicPayForId.objects.all(), 'customers.periodicpayforid')
batch_save(app_label, 'customers_tels.json', PeriodicPayForId.objects.all(), 'customers.periodicpayforid')
def dump_networks(): def dump_networks():
from ip_pool.models import NetworkModel from ip_pool.models import NetworkModel
batch_save('nets.json', NetworkModel.objects.all(), 'networks.networkmodel', choice_list_map={
app_label = 'networks'
batch_save(app_label, 'nets.json', NetworkModel.objects.all(), 'networks.networkmodel', choice_list_map={
'kind': { 'kind': {
'inet': 1, 'inet': 1,
'guest': 2, 'guest': 2,
@ -234,7 +245,8 @@ def dump_networks():
def dump_tasks(): def dump_tasks():
from taskapp.models import Task, ExtraComment, ChangeLog from taskapp.models import Task, ExtraComment, ChangeLog
batch_save('task.json', Task.objects.all(), 'tasks.task', field_name_map={
app_label = 'tasks'
batch_save(app_label, 'task.json', Task.objects.all(), 'tasks.task', field_name_map={
'abon': 'customer' 'abon': 'customer'
}, except_fields=['attachment'], choice_list_map={ }, except_fields=['attachment'], choice_list_map={
'priority': { 'priority': {
@ -257,8 +269,8 @@ def dump_tasks():
'ot': 12 'ot': 12
} }
}) })
batch_save('task_comments.json', ExtraComment.objects.all(), 'tasks.extracomment')
batch_save('task_log.json', ChangeLog.objects.all(), 'tasks.changelog', choice_list_map={
batch_save(app_label, 'task_comments.json', ExtraComment.objects.all(), 'tasks.extracomment')
batch_save(app_label, 'task_log.json', ChangeLog.objects.all(), 'tasks.changelog', choice_list_map={
'act_type': { 'act_type': {
'e': 1, 'c': 2, 'e': 1, 'c': 2,
'd': 3, 'f': 4, 'b': 5 'd': 3, 'f': 4, 'b': 5
@ -266,10 +278,21 @@ def dump_tasks():
}) })
def dump_fin():
from finapp.models import PayAllTimeGateway, AllTimePayLog
app_label = 'fin_app'
batch_save(app_label, 'fin_gws.json', PayAllTimeGateway.objects.all(), 'fin_app.payalltimegateway')
batch_save(app_label, 'fin_logs.json', AllTimePayLog.objects.all(), 'fin_app.alltimepaylog', field_name_map={
'abon': 'customer',
'summ': 'sum'
})
all_migrs = ( all_migrs = (
dump_groups, dump_accounts, dump_messenger, dump_groups, dump_accounts, dump_messenger,
dump_services, dump_gateways, dump_devices, dump_services, dump_gateways, dump_devices,
dump_customers, dump_networks, dump_tasks
dump_customers, dump_networks, dump_tasks,
dump_fin
) )
if __name__ == '__main__': if __name__ == '__main__':

2
periodic.py

@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/var/www/djing/venv/bin/python
import os import os
from threading import Thread from threading import Thread
import django import django

33
requirements.txt

@ -1,31 +1,30 @@
wheel
urllib3
Django>=2
Pillow
urllib3==1.25.10
Django==2.2.17
Pillow==7.2.0
# for mac address field # for mac address field
netaddr
netaddr==0.8.0
# for testing required xmltodict # for testing required xmltodict
#xmltodict #xmltodict
dicttoxml
dicttoxml==1.7.4
# db client for Mariadb # db client for Mariadb
mysqlclient mysqlclient
easysnmp
pid
django-guardian
pinax-theme-bootstrap
django-bootstrap3
git+git://github.com/nerosketch/easysnmp.git#egg=easysnmp
pid==3.0.4
django-guardian==2.3.0
pinax-theme-bootstrap==8.0.1
django-bootstrap3==14.1.0
# django-jsonfield # django-jsonfield
-e git://github.com/dmkoch/django-jsonfield.git#egg=django-jsonfield -e git://github.com/dmkoch/django-jsonfield.git#egg=django-jsonfield
requests
webdavclient
transliterate
django-encrypted-model-fields
requests==2.24.0
webdavclient==1.0.8
transliterate==1.10.2
django-encrypted-model-fields==0.5.8
# django-xmlview for pay system allpay # django-xmlview for pay system allpay
-e git://github.com/nerosketch/django-xmlview.git#egg=django-xmlview -e git://github.com/nerosketch/django-xmlview.git#egg=django-xmlview
@ -43,5 +42,7 @@ django-encrypted-model-fields
-e git://github.com/pexpect/pexpect.git#egg=pexpect -e git://github.com/pexpect/pexpect.git#egg=pexpect
Celery Celery
redis
redis==3.5.3
celery[redis] celery[redis]
docxtpl

1
systemd_units/djing.timer

@ -3,7 +3,6 @@ Description=Run every night a job for djing
[Timer] [Timer]
OnCalendar=*-*-* 01:59:00 OnCalendar=*-*-* 01:59:00
Persistent=true
Unit=djing.service Unit=djing.service
[Install] [Install]

1
systemd_units/djing_backup.timer

@ -3,7 +3,6 @@ Description=Run backup periodically
[Timer] [Timer]
OnCalendar=*-*-* 8,12,14,16,19,23:15:0 OnCalendar=*-*-* 8,12,14,16,19,23:15:0
Persistent=true
Unit=djing_backup.service Unit=djing_backup.service
[Install] [Install]

7
systemd_units/webdav_backup.py

@ -9,14 +9,15 @@ options = {
'webdav_login': "YANDEX USERNAME", 'webdav_login': "YANDEX USERNAME",
'webdav_password': "YANDEX PASSWORD" 'webdav_password': "YANDEX PASSWORD"
} }
REMOTE_DIR = 'DjingBackups'
def remove_old_files(border_time: datetime, client): def remove_old_files(border_time: datetime, client):
# files that older than border_time will be removed # files that older than border_time will be removed
for file in client.list('ISBackups'):
for file in client.list(REMOTE_DIR):
fdate = datetime.strptime(file, 'djing%Y-%m-%d_%H.%M.%S.sql.gz') fdate = datetime.strptime(file, 'djing%Y-%m-%d_%H.%M.%S.sql.gz')
if fdate < border_time: if fdate < border_time:
del_fname = os.path.join('ISBackups', file)
del_fname = os.path.join(REMOTE_DIR, file)
client.clean(del_fname) client.clean(del_fname)
print("rm %s" % del_fname) print("rm %s" % del_fname)
@ -30,7 +31,7 @@ if __name__ == '__main__':
remove_old_files(border_time, client) remove_old_files(border_time, client)
else: else:
client.upload_sync( client.upload_sync(
remote_path=os.path.join('ISBackups', reqfile),
remote_path=os.path.join(REMOTE_DIR, reqfile),
local_path=os.path.join(os.path.sep, 'var', 'backups', reqfile) local_path=os.path.join(os.path.sep, 'var', 'backups', reqfile)
) )
except wc.WebDavException as we: except wc.WebDavException as we:

8
tariff_app/custom_tariffs.py

@ -1,14 +1,12 @@
# -*- coding: utf-8 -*-
from datetime import timedelta, datetime, date from datetime import timedelta, datetime, date
from typing import AnyStr
from calendar import monthrange from calendar import monthrange
from random import uniform
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from .base_intr import TariffBase, PeriodicPayCalcBase from .base_intr import TariffBase, PeriodicPayCalcBase
from random import uniform
class TariffDefault(TariffBase): class TariffDefault(TariffBase):
description = _('Base calculate functionality') description = _('Base calculate functionality')
@ -101,7 +99,7 @@ class PeriodicPayCalcDefault(PeriodicPayCalcBase):
today = date.today() today = date.today()
nw = datetime(today.year, today.month, today.day) nw = datetime(today.year, today.month, today.day)
days = monthrange(nw.year, nw.month)[1] days = monthrange(nw.year, nw.month)[1]
return nw + timedelta(days - nw.day+1)
return nw + timedelta(days - nw.day + 1)
class PeriodicPayCalcCustom(PeriodicPayCalcDefault): class PeriodicPayCalcCustom(PeriodicPayCalcDefault):

6
templates/base.html

@ -129,6 +129,12 @@
</a> </a>
</li> </li>
{% url 'docsapp:docs_list' as docslist %}
<li{% if docslist in request.path %} class="active"{% endif %}>
<a href="{{ docslist }}">
<span class="glyphicon glyphicon-book"></span> {% trans 'Documents' %}
</a>
</li>
</ul> </ul>
</div> </div>

2
templates/custom_pages/footer.htm

@ -1 +1 @@
Your custom content <i>here</i>.
{# Your custom content <i>here</i>. #}

2
templates/custom_pages/main_page.htm

@ -1 +1 @@
<h1>You can change this page</h1>
{# <h1>You can change this page</h1> #}

4
templates/custom_pages/service.htm

@ -1,2 +1,2 @@
<h1>Your custom content</h1>
<p>You have service variable {{ active_service }}</p>
{# <h1>Your custom content</h1> #}
{# <p>You have service variable {{ active_service }}</p> #}

2
templates/custom_pages/service_bottom.htm

@ -1 +1 @@
<h1>Your custom content on bottom</h1>
{# <h1>Your custom content on bottom</h1> #}
Loading…
Cancel
Save