Создание отчётов — различия между версиями
Admin (обсуждение | вклад) (→Накладная на карты) |
Admin (обсуждение | вклад) (→Накладная на карты) |
||
Строка 303: | Строка 303: | ||
</div> | </div> | ||
− | <div style="font-weight:bold; float:left; width:100%; text-align:center; margin-bottom:20px; margin-top:20px; ">Накладная от ${created}</div> | + | <div style="font-weight:bold; float:left; width:100%; text-align:center; margin-bottom:20px; margin-top:20px; "> |
+ | Накладная от ${created} | ||
+ | </div> | ||
<div style="clear:both "></div> | <div style="clear:both "></div> | ||
Строка 335: | Строка 337: | ||
</pre> | </pre> | ||
− | + | Результат работы шаблона: | |
− | [[Файл:sale_card.png|center]] | + | [[Файл:sale_card.png|center|640px]] |
== Документация по синтаксису шаблонов == | == Документация по синтаксису шаблонов == | ||
* http://www.makotemplates.org/ | * http://www.makotemplates.org/ |
Версия 13:53, 16 марта 2011
В ExpertBilling 1.4 внедрена принципиально новая система работы с отчётами. Сейчас вы сами сможете задать их внешний вид, а, также, создавать новые виды отчётов и документов. Из тела отчёта можно обратиться к rpc серверу, выполнить выборки из базы данных и отформатировать их в удобном для вас виде.
Свои отчёты вы можете сделать интерактивными. К примеру, перед его формированием, предложить пользователю указать необходимый период времени или выбрать другие параметры.
Для генерации отчётов необходимо создать шаблоны отчётов. Сделать это можно в меню "Главное меню"->"Шаблоны документов"
В левой части окна расположены категории отчётов. Часть отчётов предзадана и мы не рекомендуем их удалять. Чтобы создать новый отчёт необходимо выбрать первый пункт в дереве типов шаблонов "-- Новый шаблон --" и указать параметры шаблона справа. Выберите тип шаблона, его имя и задайте тело шаблона. С помощью кнопки "Сохранить" на панели инструментов сохраните его. Кнопка "Предпросмотр" служит для предварительного просмотра созданного шаблона
Содержание
Краткая информация по синтаксису шаблонов
Обозначение переменных:
${value1} ${object.value}
Вызов функций и методов
${int(a)} ${object.method()}
Вычисления
${a+100} ${(1/2)+200**7}
Выполнение кода на языке python в теле отчёта
<% import datetime #получение текущего времени now = datetime.datetime.now() %>
Цикл for в теле отчёта
%for account in accounts: ${account.id}, ${account.username} %endfor
Получение списка доступных переменных и методов в объекте ${dir(object)}
Пример, демонстрирующий работу функции: Код:
<% #получаем учётную запись пользователя с id=100 account=connection.get_model(100, "billservice_account") %> ${dir(account)}
Результат: ['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_asdict', '_fromTuple', '_toTuple', 'address', 'allow_expresscards', 'allow_ipn_with_block', 'allow_ipn_with_minus', 'allow_ipn_with_null', 'allow_vpn_block', 'allow_vpn_null', 'allow_webcab', 'assign_dhcp_block', 'assign_dhcp_null', 'assign_ipn_ip_from_dhcp', 'associate_pppoe_mac', 'associate_pptp_ipn_ip', 'balance_blocked', 'ballance', 'city', 'city_id', 'comment', 'contactperson', 'contactperson_phone', 'contract', 'created', 'credit', 'delete', 'disabled_by_limit', 'elevator_direction', 'email', 'entrance', 'entrance_code', 'fullname', 'get', 'hasattr', 'house', 'house_bulk', 'house_id', 'id', 'ipn_added', 'ipn_ip_address', 'ipn_ipinuse_id', 'ipn_mac_address', 'ipn_speed', 'ipn_status', 'isnull', 'last_balance_null', 'nas_id', 'passport', 'passport_date', 'passport_given', 'password', 'phone_h', 'phone_m', 'postcode', 'private_passport_number', 'region', 'room', 'row', 'save', 'status', 'street', 'street_id', 'suspended', 'systemuser_id', 'username', 'vlan', 'vpn_ip_address', 'vpn_ipinuse_id', 'vpn_speed']
Видим все доступные переменные из учётной записи пользователя. Чтобы вставить в тело отчёта телефонный номер абонента, нужно написать ${account.phone_m}, баланс - ${account.ballance} и т.д.
Доступ к rpc серверу из отчёта
В самом начале работы отчёта уже присутствует переменная connection, которая хранит в себе подключение к rpc серверу. Доступ к rpc серверу понадобится вам в том случае, если вы захотите получить доступ к данным, хранящимся в базе данных. Помимо доступа к данным вам будут доступны другие функции rpc сервера. Такие как сброс активной сессии на севрере доступа, активация/деактивация пользователя на сервере доступа и многие другие. Основные функции
- sql() - выполнение запроса. Функция возвращает результат вопроса в виде списка объектов записей
- get_model(id, table_name) - получить конкретную запись из указанной таблицы по её id
- get_models(table_name) - получить список записей из указанной таблицы
Пример:
<% accounts = connection.get_models("billservice_account") %> <table> <tr> <td>id</td><td>username</td> </tr> %for account in accounts: <tr> <td>${account.id}</td><td>${account.username}</td> </tr> %endfor </table>
В примере производится выборка всех аккаунтов и вывод их id и имён пользователей в виде таблицы.
Пример отчёта
Этот отчёт запрашивает период времени и потом показывает суммы, на которые был пополнен баланс у каждого пользователя.
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <% import os from CustomForms import PeriodForm child = PeriodForm(realm='ostatok') if child.exec_()!=1: return %> <% accounts = connection.get_models("billservice_account") %> <img src="${os.path.abspath("images/reports/header.png")}"> <center>Пополнения баланса за период <strong>С ${child.start_date}</strong> по <strong>${child.end_date}</strong></center> <table border=1 width=100%> <tr> <td>Имя пользователя</td><td>ФИО</td><td>Сумма</td> </tr> % for account in accounts: <% account_summ = connection.sql(r"SELECT sum(summ) FROM billservice_transaction WHERE account_id=%s and created between '%s' and '%s';" % (account.id, child.start_date, child.end_date))[0].sum or 0 %> <tr> <td>${account.username}</td><td>${account.fullname}</td><td>${account_summ}</td> </tr> % endfor </body> </html>
Отчёт по vpn сессиям абонентов
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <% import os from CustomForms import PeriodForm child = PeriodForm(realm='ostatok') if child.exec_()!=1: return %> <% sessions = connection.sql("SELECT account_id, count(*) as sess_acount, (SELECT username FROM billservice_account as acc WHERE acc.id=account_id) as username, sum(bytes_in) as bytes_in, sum(bytes_out) as bytes_out FROM radius_activesession WHERE date_start between '%s' and '%s' GROUP BY account_id" % (child.start_date, child.end_date)) %> <img src="${os.path.abspath("images/reports/header.png")}"> <center>Объём трафика по vpn сессиям<strong>С ${child.start_date}</strong> по <strong>${child.end_date}</strong></center> <table border=1 width=100%> <tr> <td>Имя пользователя</td><td>Принято</td><td>Отправлено</td><td>Количество сессий абонента</td> </tr> % for session in sessions: <tr> <td>${session.username}</td><td>${int((session.bytes_in or 0)/(1024*1024))} МБ</td><td>${int((session.bytes_out or 0)/(1024*1024))} МБ</td><td>${session.sess_acount}</td> </tr> % endfor </body> </html>
Результат:
Встроенные документы
В системе существуют следующие виды шаблонов:
- Договор на подключение физ.лица
- Договор на подключение юр.лица
- Накладная на карты
- Шаблон карты
- Кассовый чек
- Информационное письмо
- Акт выполненных работ
- Счёт-фактура
- Отчёты
Договор на подключение физ.лица
Система позволяет создать несколько шаблонов этого типа. В тело шаблона передаётся список из идентификаторов аккаунтов,если выбрана печать договоров для списка пользователей, или список, состоящий из одного элемента - id аккаунта, если печать производится из карточки аккаунта.
Доступные пременные:
accounts - тип список connection - подключение к rpc серверу
Пример шаблона:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <% import os provider = connection.get_operator()[0] %> <img src="${os.path.abspath("images/reports/header.png")}"> %for account_id in accounts: <% account = connection.get_model(account_id, "billservice_account") %> ID: ${account.id}<br> Договор номер ${account.contract}<br> %endfor </body> </html>
Для печати договора вам потребуется заполнить информацию о провайдере в меню Help->About Operator Получить эту информацию в шаблоне можно с помощью такой конструкции
provider = connection.get_operator()[0]
Список доступных полей у переменной provider:
id organization - название unp okpo contactperson director phone postaddress uraddress email fax bank_id
Получить информацию о банке можно с помощью конструкции
bank = connection.get_model(provide.bank_id, "billservice_bankdata")
Доступные переменные:
id bank bankcode rs
Договор на подключение юр.лица
Печать договора на подключение юр. лица ничем не отличается от физ. лиц за тем исключением, что для получения доступа к расширенному набору полей юрлиц вам необходимо воспользоваться конструкцией:
org = connection.get("SELECT * FROM billservice_organization WHERE account_id=%s" % account.id)
Доступные переменные:
id account_id name uraddress okpo unp bank_id phone fax kpp kor_s
Получить банк вы можете способом, описанным выше в шаблоне для физ. лиц.
Накладная на карты
Этот тип документа описывает факт передачи партии карт доступа/экспресс-оплаты/HotSpot дилеру. В шаблон передаётся список объектов карт в переменной cards, объект с информацией о провайдере в переменной operator, объект дилера в переменной dealer, текущая дата в переменной created, cardcount - количество продаваемых карт, sum_for_pay - сумма к оплате, pay - сколько оплачено, discount - процент скидки, discount_sum - сумма скидки, paydeffer - отсрочка оплаты в днях.
Вид шаблона по-умолчанию:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> </head> <body> <div style="width:100%; "> <div style="float:right "> <span style="font-weight:bold; ">Дилер</span><br> Организация: ${dealer.organization}<br> Директор: ${dealer.director}<br> Юр адрес: ${dealer.uraddress}<br> р/с: ${dealer.rs}<br> УНН: ${dealer.unp}<br> ОКПО: ${dealer.okpo}<br> Банк: ${dealer.bank}, код ${dealer.bankcode}<br> </div> <div style="float:left "> <span style="font-weight:bold; ">Оператор</span><br> Организация: ${operator.organization}<br> Директор: ${operator.director}<br> Юр адрес: ${operator.uraddress}<br> р/с: ${operator.rs} <br> УНН: ${operator.unp}<br> ОКПО: ${operator.okpo}<br> Банк: ${operator.bank}, Код ${operator.bankcode}<br> </div> </div> <div style="font-weight:bold; float:left; width:100%; text-align:center; margin-bottom:20px; margin-top:20px; "> Накладная от ${created} </div> <div style="clear:both "></div> <table border="1" align="center" style="width:100%"> <tr> <td>ID карты</td> <td>Серия</td> <td>Номинал</td> <td>Активировать С</td> <td>Активировать По</td> </tr> % for card in cards: <tr> <td>${card.id}</td> <td>${card.series}</td> <td>${card.nominal}</td> <td>${card.start_date}</td> <td>${card.end_date}</td> </tr> % endfor </table> Итого ${cardcount} карт на сумму: ${sum_for_pay}<br> Скидка: ${discount} на сумму ${discount_sum}<br> Оплачено: ${pay}<br> Оплатить до:${paydeffer} </body> </html>
Результат работы шаблона: