You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

199 lines
7.2 KiB

# -*- coding: utf-8 -*-
from django import forms
from django.shortcuts import render
from django.views.decorators.csrf import csrf_protect
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.auth.decorators import permission_required
from django.utils.encoding import force_text
from django.conf import settings
import xlrd
from .models import Fond, FondStats
from .forms import AdminBaseImportForm, AdminFondStatsImportForm
DEBUG_IMPORT = getattr(settings, 'DEBUG_NPF_IMPORT', False)
def _getval_str(row, cx):
"""Взять значение из колонки внутри переданной строки.
Если значение прочитано из экселя как float вида 123.0, то .0 отбрасывается.
Иначе значение берётся как есть.
Всегда возвращает строку, начальные и хвостовые пробелы отрезаются.
"""
val = row[cx].value
if isinstance(val, float) and val - int(val) == 0:
val = int(val)
return force_text((u'%s' % val).strip())
def _getval_int(row, cx):
"""Взять целое значение из колонки внутри переданной строки.
Возвращает число или выбрасывает ошибку конвертации.
"""
val = row[cx].value
return int(val)
def _getval_int_or_none(row, cx):
"""Взять целое значение из колонки внутри переданной строки.
Возвращает число или None в случае ошибки конвертации.
"""
val = row[cx].value
try:
return int(val)
except ValueError:
return None
def _getval_float_or_none(row, cx):
"""Взять float из колонки внутри переданной строки.
Возвращает число или None в случае ошибки конвертации.
"""
val = row[cx].value
try:
return float(val)
except ValueError:
return None
@csrf_protect
@staff_member_required
@permission_required('can_import_export_fond', raise_exception=True)
def revise_licenses(request):
"""Сверка лицензий НПФ."""
IDX_LICENSE = 0 # номер лицензии
xls_file = None
new_licenses = None
closed_licenses = None
start_nrow = 1 # с какой строки начинать импорт из файла (отсчёт с нуля)
form_class = AdminBaseImportForm
if request.method == 'GET':
form = form_class()
else:
form = form_class(request.POST, request.FILES)
if request.method == 'POST' and form.is_valid():
xls_file = request.FILES['xls_file']
xls_to_import = xls_file.read()
book = xlrd.open_workbook(file_contents=xls_to_import)
sh = book.sheet_by_index(0)
# все лицензии в файле
xls_licenses = set([_getval_str(sh.row(rx), IDX_LICENSE) for rx in xrange(start_nrow, sh.nrows)])
# все лицензии на сайте
db_licenses = set(Fond.objects.all().order_by('license').values_list('license', flat=True))
# лицензии, которые есть в файле, но отсутствуют на сайте (новые фонды)
new_licenses = xls_licenses.difference(db_licenses)
# лицензии, которые есть на сайте, но отсутствуют в файле (закрывшиеся фонды)
closed_licenses = db_licenses.difference(xls_licenses)
return render(request, 'admin/npfs/revise_licenses.html',
{
'form': form,
'xls': xls_file,
'new_licenses': new_licenses,
'closed_licenses': closed_licenses,
},
)
@csrf_protect
@staff_member_required
@permission_required('can_imp_exp_fond_stats', raise_exception=True)
def import_fond_stats(request):
"""Импорт основных показателей НПФ."""
import_errors = []
err_license_not_found = []
xls_file = None
wrong_file = None
start_nrow = 4 # с какой строки начинать импорт из файла (отсчёт с нуля)
form_class = AdminFondStatsImportForm
if request.method == 'GET':
form = form_class()
else:
form = form_class(request.POST, request.FILES)
if request.method == 'POST' and form.is_valid():
xls_file = request.FILES['xls_file']
xls_to_import = xls_file.read()
book = xlrd.open_workbook(file_contents=xls_to_import)
sh = book.sheet_by_index(0)
god = int(form.cleaned_data['god'])
kvartal = int(form.cleaned_data['kvartal'])
# закешировать НПФ в словарь. ключ номер лицензии
fond_cache = {_fond.license: _fond for _fond in Fond.objects.all()}
rx = 0
for rx in xrange(start_nrow, sh.nrows):
row = sh.row(rx)
try:
license = _getval_str(row, 0)
if not license:
raise Exception(u'Не указан `№ лицензии` в строке номер %d!' % (rx+1))
try:
fond = fond_cache[license]
except KeyError:
err_license_not_found.append(rx + 1)
raise Exception(u'Не найден `НПФ` в строке номер %d!' % (rx+1))
fond_stats, created = FondStats.objects.get_or_create(
fond=fond, god=god, kvartal=kvartal)
fond_stats.imusch = _getval_float_or_none(row, 2)
fond_stats.kapital = _getval_float_or_none(row, 3)
fond_stats.ioud = _getval_float_or_none(row, 4)
fond_stats.pens_rezerv = _getval_float_or_none(row, 5)
fond_stats.pens_nakopl = _getval_float_or_none(row, 6)
fond_stats.obyazat = _getval_float_or_none(row, 7)
fond_stats.pens_nakopl_rynok = _getval_float_or_none(row, 8)
fond_stats.num_zastrah = _getval_int_or_none(row, 9)
fond_stats.num_zastrah_pens = _getval_int_or_none(row, 10)
fond_stats.pens_ops = _getval_float_or_none(row, 11)
fond_stats.num_chel = _getval_int_or_none(row, 12)
fond_stats.num_chel_pens = _getval_int_or_none(row, 13)
fond_stats.vyplat_npo = _getval_float_or_none(row, 14)
fond_stats.dohod_razmesch = _getval_float_or_none(row, 15)
fond_stats.dohod_invest = _getval_float_or_none(row, 16)
fond_stats.save()
except:
if DEBUG_IMPORT:
raise
else:
import_errors.append(rx + 1)
if rx + 1 > len(import_errors):
wrong_file = False
else:
wrong_file = True
return render(request, 'admin/npfs/fond_stats.html',
{
'form': form,
'import_errors': import_errors,
'err_license_not_found': err_license_not_found,
'xls': xls_file,
'wrong_file': wrong_file,
},
)