BiTel

Форум BiTel
bgbilling.ru     docs.bitel.ru     wiki.bitel.ru     dbinfo.bitel.ru     bgcrm.ru     billing.bitel.ru     bitel.ru    
Текущее время: 25 июн 2025, 03:56

Часовой пояс: UTC + 5 часов [ Летнее время ]




Начать новую тему Ответить на тему  [ Сообщений: 16 ] 
Автор Сообщение
 Заголовок сообщения: Рассылка напоминаний должникам
СообщениеДобавлено: 28 апр 2014, 09:21 
Не в сети
Клиент

Зарегистрирован: 13 апр 2012, 21:24
Сообщения: 345
Карма: 0
Необходимо тем, у кого задолженность больше заданной раз в неделю капать на мозги, что мол у вас задолженность, срочно оплатите.
Тыкните пожалуйста носом в документацию, где написано как это сделать...
Спасибо.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 28 апр 2014, 09:57 
Не в сети
Клиент
Аватара пользователя

Зарегистрирован: 16 сен 2010, 11:53
Сообщения: 501
Карма: 15
у нас есть глобальный скрипт, который посылает смс абонентам за 1,2,5 дней до отключения. надо?

_________________
Клиент: вер. 7.0.806 / 29.04.2016 13:18:28 os: Windows 7; java: Java HotSpot(TM) Client VM, v.1.8.0_66
Сервер: вер. 7.0.1035 / 29.04.2016 13:17:38 os: Linux; java: Java HotSpot(TM) 64-Bit Server VM, v.1.8.0_92


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 28 апр 2014, 10:25 
Не в сети
Клиент

Зарегистрирован: 13 апр 2012, 21:24
Сообщения: 345
Карма: 0
У нас нет "отключения", специфика бизнеса.
У нас есть абоненты, которые пока им лично не позвонишь - присланные счета игнорируют.
Нужно для тех, кто задолжал определенную сумму - навязчиво слать уведомления.
Предел суммы вполне можно брать из лимита договора.
PS. А почему "скрипт" ? штатных средств нету что-ли ?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 28 апр 2014, 10:30 
Не в сети
Клиент
Аватара пользователя

Зарегистрирован: 16 сен 2010, 11:53
Сообщения: 501
Карма: 15
скрипт и есть штатное средство. в этом вся прелесть бг

_________________
Клиент: вер. 7.0.806 / 29.04.2016 13:18:28 os: Windows 7; java: Java HotSpot(TM) Client VM, v.1.8.0_66
Сервер: вер. 7.0.1035 / 29.04.2016 13:17:38 os: Linux; java: Java HotSpot(TM) 64-Bit Server VM, v.1.8.0_92


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 28 апр 2014, 11:39 
Не в сети
Клиент
Аватара пользователя

Зарегистрирован: 29 мар 2010, 23:11
Сообщения: 5854
Карма: 472
Модуль dispatch. Штатное средство на скриптах )

_________________
Цитаты великих людей :umnik:
Напишите в helpdesk © stark
повторяю: => хелпдеск => доработка => профит © dimOn
свершилось... © skn
Мой код изящен, лёгок, оригинален, краток. Как прохладный весенний ветерок, как звонкий ручей! © dimOn
Вежливый разработчик © Artur
Эти баги тоже исправлены, как и те, которые еще не написаны © Artur
ну т.е. существует воркэраунд, ок © dimOn


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 28 апр 2014, 11:47 
Не в сети
Клиент

Зарегистрирован: 13 апр 2012, 21:24
Сообщения: 345
Карма: 0
У меня тут приятель БМВ подержанную купил. 5ку, в последнем кузове. На форум полез, там увидел обсуждение того, что она прямо не едет, народ советовал "повернуть пружины", а если не поможет - ехать к дилеру и покупать опцию "движение прямо"... во как... Движение прямо это теперь опция )


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 29 апр 2014, 12:43 
Не в сети
Клиент

Зарегистрирован: 07 мар 2012, 15:02
Сообщения: 932
Откуда: Воронеж
Карма: 35
Я для рассылки SMS написал задачу для шедулера. Раньше тоже было через скрипты, но не глобальные. Пробовал через модуль dispatch, но там много лишнего получается и нужно менять логику работы с контактными данными абонентов. Гораздо проще и эффективнее было написать задачу для шедулера. А уже в задаче можно реализовать любую логику для рассылки уведомлений.

_________________

Клиент: вер. 6.2.873 / 04.12.2017 19:38:11
os: Windows 7; java: Java HotSpot(TM) 64-Bit Server VM, v.1.8.0_65
Сервер: вер. 6.2.1202 / 04.12.2017 19:39:21
os: Linux; java: Java HotSpot(TM) 64-Bit Server VM, v.1.8.0_91


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 04 май 2014, 04:15 
Не в сети
Клиент

Зарегистрирован: 13 апр 2012, 21:24
Сообщения: 345
Карма: 0
поделитесь вашей задачей для образца мне ?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 06 май 2014, 15:43 
Yarlan Zey писал(а):
у нас есть глобальный скрипт, который посылает смс абонентам за 1,2,5 дней до отключения. надо?

Если возможно, поделитесь с нами ....


Вернуться к началу
  
 
СообщениеДобавлено: 06 май 2014, 16:31 
Не в сети
Клиент
Аватара пользователя

Зарегистрирован: 16 сен 2010, 11:53
Сообщения: 501
Карма: 15
Код:
//Отправка СМС с напоминанием о приближающейся блокировке

import bitel.billing.server.contract.bean.BalanceUtils;
import bitel.billing.server.contract.bean.ContractStatus;
import bitel.billing.server.contract.bean.ContractStatusManager;
import java.math.*;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import ru.bitel.bgbilling.modules.npay.server.Calculator;
import java.text.SimpleDateFormat;
import java.net.*;
import java.io.*;

public void main( setup, con, conSlave )
{

//Начало функции подсчета суммы оплаты за n-количество дней
public static double payday (StartDate, int days) {
    double result = 0;//переменная в которой будет содержаться результат
   payday = 0;
   paymonth = 0;
   paymonthtoday = 0;
   String DateQuery = StartDate;
    for (int i = 0; i < days; i++)
      {

//Достаем сумму списания в день на сегодня
querytoday =    "SELECT ROUND(SUM(REPLACE(data,'type&1%cost&',''))/EXTRACT(DAY FROM LAST_DAY('"+DateQuery+"')),3) as ap FROM module_tariff_tree as a " +
            "LEFT JOIN mtree_node AS b ON (a.id=b.mtree_id) " +
            "LEFT JOIN contract_tariff AS c ON (c.tpid=a.tree_id) " +
            "WHERE (a.mid=7)AND(type LIKE \"%cos%t\")AND(c.cid="+cid+")AND(c.date1<='"+DateQuery+"')AND((c.date2 is NULL)OR(c.date2>='"+DateQuery+"'))AND(type='day_cost')";
PreparedStatement psSelect = conSlave.prepareStatement(querytoday);
ResultSet rs = psSelect.executeQuery();
    while (rs.next())
       {
   payday = rs.getDouble(1);
      }
psSelect.close();   

//Достаем сумму списания в месяц на сегодня
querytoday =    "SELECT IFNULL(ROUND(SUM(REPLACE(data,'type&0%cost&',''))/EXTRACT(DAY FROM LAST_DAY('"+DateQuery+"')),3),0) as ap FROM module_tariff_tree as a " +
            "LEFT JOIN mtree_node AS b ON (a.id=b.mtree_id) " +
            "LEFT JOIN contract_tariff AS c ON (c.tpid=a.tree_id) " +
            "WHERE (a.mid=7)AND(type LIKE \"%cos%t\")AND(c.cid="+cid+")AND(c.date1<='"+DateQuery+"')AND((c.date2 is NULL)OR(c.date2>='"+DateQuery+"'))AND(type='month_cost')AND(DAYOFMONTH('"+DateQuery+"')=1)";
PreparedStatement psSelect = conSlave.prepareStatement(querytoday);
ResultSet rs = psSelect.executeQuery();
    while (rs.next())
       {
   paymonth = rs.getDouble(1);
      }
psSelect.close();   

result = result + payday + paymonth;

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar c = Calendar.getInstance();
c.setTime(sdf.parse(DateQuery));
c.add(Calendar.DATE, 1);  // +1 день
DateQuery = sdf.format(c.getTime());  // Новая дата
    }
    return result;//возвращаю его
}
//Конец функции подсчета суммы оплаты за n-количество дней

//Достаем сегодняшнюю дату
Date currentDate = new Date();

//Достаем параметры договоров
String query = "SELECT a.id, b.value, SUBSTRING(f.title,1,1), CONCAT(e.house, '', e.frac), d.flat " + //c.summa1+c.summa2-c.summa3-c.summa4,
            "FROM contract AS a " +
            "LEFT JOIN contract_parameter_type_phone AS b ON (b.cid=a.id) " +
//            "LEFT JOIN contract_balance AS c ON ((c.cid=a.id) AND (c.mm=month(now())) AND (c.yy=year(now()))) " +
            "LEFT JOIN contract_parameter_type_2 AS d ON (d.cid=a.id) " +
            "LEFT JOIN address_house AS e ON (d.hid=e.id) " +
            "LEFT JOIN address_street AS f ON (f.id=e.streetid) " +
            "LEFT JOIN contract_module AS g ON (g.cid=a.id) " +
            "LEFT JOIN ipn_contract_status_9 AS h ON (h.cid=a.id) " +
            "WHERE (a.status=0) AND NOT ISNULL(b.value) AND (g.mid=9) AND (h.status=0)"; //AND ((c.summa1+c.summa2-c.summa3-c.summa4)>0)
   PreparedStatement contractPs = con.prepareStatement( query );
   ResultSet contractRs = contractPs.executeQuery();
   int cid;
   String ContractPhone = "";
   int ksms = 0;
   int ksms1 = 0;
   int ksms5 = 0;

while ( contractRs.next() )
    {
      cid = contractRs.getInt( 1 );
//print (cid +" start");
      ContractPhone = contractRs.getString( 2 );
      ContractPhone = ContractPhone.replace("; ", ",");//Заменяем точку с запятой и пробел на запятую (требование СМС пилота)
      //balance = contractRs.getDouble( 3 );
      BalanceUtils bu = new BalanceUtils( con );
      BigDecimal bal = bu.getBalance(currentDate, cid);
      double balance = bal.doubleValue();
if (balance > 0) {
      Street = contractRs.getString(3);
      H = contractRs.getBytes(4);
      String House = new String(H,"cp1251");
      Flat = contractRs.getString(5);
      Adress = Street + ". " + House + "-" + Flat;

SMSText2 = "";

//Применяем к дате маску для использования в СМС-Пилоте
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
senddt = sdf.format(currentDate);

//Забираем суммы оплат на ближайшие дни
double paytoday = payday(senddt,1);//Сумма оплаты на 1 день
double payto2day = payday(senddt,2);//Сумма оплаты на 2 дня
//double payto3day = payday(senddt,3);//Сумма оплаты на 3 дня
double payto5day = payday(senddt,5);//Сумма оплаты на 5 дней
double payto6day = payday(senddt,6);//Сумма оплаты на 6 дней

   if (balance < payto2day && balance >=paytoday) {
      SMSText2 = URLEncoder.encode(" руб. До блокировки 1 день.", "UTF-8") + "&to=";
      ksms1++;;
      }
/*   else if (balance < payto3day && balance >= payto2day) {
      SMSText2 = URLEncoder.encode(" руб. До блокировки 2 дня.", "UTF-8") + "&to=";
      }*/
   else if (balance < payto6day && balance >= payto5day) {
      SMSText2 = URLEncoder.encode(" руб. До блокировки 5 дней.", "UTF-8") + "&to=";
      ksms5++;
      }

   if (SMSText2 != "") {
balance = balance - paytoday;
balance = Math.rint(100.0 * balance) / 100.0;
SMSSend = "";
SMSSender = "";
APIKey = "";
SMSSend = "http://smspilot.ru/api.php?send=" + URLEncoder.encode("Баланс ", "UTF-8") + URLEncoder.encode(Adress, "UTF-8") + ": " + balance + SMSText2 + ContractPhone + "&from=" + SMSSender + "&apikey=" + APIKey + "&send_datetime=" + senddt + " 05:00:00";
print ("Абонент: " + cid + " SMS: " + balance + URLDecoder.decode (SMSText2));

// -- START SENDING SMS MESSAGE --
URL url = new URL(SMSSend);
URLConnection c = url.openConnection();
BufferedReader in = new BufferedReader(
new InputStreamReader(
c.getInputStream()));
String inputLine;

while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
// -- END SENDING SMS MESSAGE --

ksms++;
}
}
}
print("Кол-во отправленных СМСок " +ksms );
print("Из них:");
print("1 день " +ksms1 );
print("5 дней " +ksms5 );
contractRs.close();
contractPs.close();   
}

_________________
Клиент: вер. 7.0.806 / 29.04.2016 13:18:28 os: Windows 7; java: Java HotSpot(TM) Client VM, v.1.8.0_66
Сервер: вер. 7.0.1035 / 29.04.2016 13:17:38 os: Linux; java: Java HotSpot(TM) 64-Bit Server VM, v.1.8.0_92


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 06 май 2014, 17:30 
to Yarlan Zey
Спасибо.


Вернуться к началу
  
 
СообщениеДобавлено: 12 май 2014, 12:17 
Не в сети
Клиент

Зарегистрирован: 07 мар 2012, 15:02
Сообщения: 932
Откуда: Воронеж
Карма: 35
Не знаю, пригодиться ли... Выкладываю как есть.
Код:
package ru.provider.sms.tasks;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Calendar;
import java.util.Map;

import bitel.billing.server.contract.bean.BalanceUtils;
import bitel.billing.server.contract.bean.ContractManager;
import bitel.billing.server.npay.Calculator;
import bitel.billing.server.npay.bean.ServiceObjectManager;
import ru.bitel.bgbilling.server.util.ServerUtils;

/**
 * <p>Задача рассылки уведомлений о необходимости пополнить счёт</p>
 * <p>Ищет абонентов, у которых на счёте недостаточно средств для оплаты следующего месяца, и отправляет им уведомления</p>
 * <p>Для запуска класс необходимо скомпилировать и положить к другим библиотекам на сервере биллинга,
 * после чего добавить задачу по аналогии с другими задачами планировщика.</p>
 */
public class PeriodicSmsNotifications extends AbstractSmsTask {

   private int npayMid;
   private BalanceUtils bu;
   private Calendar currDate;
   private Calendar nextDate;
   private Map<Integer, BigDecimal> planAccountMap;

   @Override
   public String getDescription() {
      return this.defaultDescription + "Рассылка SMS уведомлений о необходимости пополнить счёт.";
   }
   
   @Override
   public boolean initTask() {
      boolean r = super.initTask();

      this.npayMid = this.taskSetup.getInt("npay.mid", 0);

      if (!r || this.npayMid == 0) {
         this.log.error("Bad task config!");
         return false;
       }

      return true;
    }

   @Override
   public void executeTask() {
      this.con = this.setup.getDBConnectionFromPool();

      this.currDate = Calendar.getInstance();

      this.nextDate = Calendar.getInstance();
      this.nextDate.set(this.currDate.get(Calendar.YEAR), this.currDate.get(Calendar.MONTH) + 1, 1);
      if (this.tariffTotal.isEmpty()){
         this.tariffTotal = "-1";
      }

      String query = "" +
            " SELECT" +
            "   c.id AS contractId," +
            "   c.title AS contractTitle," +
            "   c.closesumma AS contractLimit," +
            "   p1.val AS mobilePhone," +
            "   p2.val AS emailAddress," +
            "   t.cid" +
            " FROM" +
            "   contract c" +
            "   LEFT JOIN contract_parameter_type_1 p1 ON c.id = p1.cid AND p1.pid = " + this.mobilePid +
            "   LEFT JOIN contract_parameter_type_1 p2 ON c.id = p2.cid AND p2.pid = " + this.emailPid +
            "   LEFT JOIN contract_tariff t ON c.id = t.cid AND t.tpid IN (" + this.tariffTotal + ") AND ((NOW() BETWEEN t.date1 AND t.date2) OR (t.date1 <= NOW() AND t.date2 IS NULL))" +
            " WHERE" +
            "   c.status IN (0,3,4) AND" +
            "   c.fc = 0 AND (" +
            "      (p1.val IS NOT NULL AND p1.val != '') OR" +
            "      (p2.val IS NOT NULL AND p2.val != '')" +
            "   ) AND t.cid IS NULL";

      if (!this.workGroups.isEmpty()) {
         query += " AND (";
         for (int gid : this.workGroups) {
            query += " (c.gr >> " + gid + ") & 1" + " AND";
         }
         query += " 1=1)";
      }
      if (!this.skipGroups.isEmpty()) {
         query += " AND !(";
         for (int gid : this.skipGroups) {
            query += " (c.gr >> " + gid + ") & 1" + " OR";
         }
         query += " 0=1 )";
      }

      try {
         new ContractManager(con);
         this.bu = new BalanceUtils(con);
         new ServiceObjectManager(con, this.npayMid);

         Statement stmt = con.createStatement();
         ResultSet rs = stmt.executeQuery(query);
         
         String cids = "";
         while (rs.next()) {
            cids += rs.getInt("contractId");
             cids += ",";
         }
         
         if (cids.length() == 0) {
            this.log.info("Contracts not found");
            return;
         }

         Calculator calculator = new Calculator();
         calculator.setExecutingTime( this.nextDate );
         calculator.setPreCalc();
         calculator.initTask( setup, 0, "mid=" + this.npayMid );
         calculator.setCids( cids.substring(0, cids.length() - 1) );
         calculator.startTask();

         this.planAccountMap = calculator.getCostCache().getContractAccounts();

         rs.beforeFirst();
         while (rs.next()) {
            int contractId = rs.getInt("contractId");
            String contractTitle = rs.getString("contractTitle");
            BigDecimal contractLimit = rs.getBigDecimal("contractLimit");
            String mobilePhone = rs.getString("mobilePhone");
            String emailAddress = rs.getString("emailAddress");

             sendNotification(contractId, contractTitle, contractLimit, mobilePhone, emailAddress);
            
            sleep();
         }
         stmt.close();
      } catch (Exception ex) {
         this.log.error(ex.getMessage(), ex);
      } finally {
         ServerUtils.closeConnection(con);
      }
   }

   public void sendNotification(int contractId, String contractTitle, BigDecimal contractLimit, String mobilePhone, String emailAddress) throws UnsupportedEncodingException {
      BigDecimal balance = this.bu.getBalance(this.currDate.getTime(), contractId);
      BigDecimal totalCost = this.planAccountMap.get( contractId );
      
      if (totalCost == null) {
         this.log.info("Договор=" + contractTitle + "; limit=" + contractLimit + "; balance=" + balance + "; totalCost=" + totalCost + "; Result=ERROR!");
         return;
      }
      
      if (totalCost.compareTo(BigDecimal.ZERO) <= 0 || balance.subtract(totalCost).compareTo(contractLimit) >= 0) {
         this.log.info("Договор=" + contractTitle + "; limit=" + contractLimit + "; balance=" + balance + "; totalCost=" + totalCost + "; Result=OK!");
       } else {
          this.log.info("Договор=" + contractTitle + "; limit=" + contractLimit + "; balance=" + balance + "; totalCost=" + totalCost + "; Result=" + totalCost.subtract(balance));
         
         if (emailAddress != null && !emailAddress.isEmpty()) {
            String msg = this.emailMsgTpl;
             msg = msg.replaceAll("%title%", contractTitle);
            msg = msg.replaceAll("%balance%", balance.toString());
            msg = msg.replaceAll("%result%", totalCost.subtract(balance).toString());

            sendEmailNotification(emailAddress, "Недостаточный баланс", msg);
         }
         
         if (mobilePhone != null && !mobilePhone.isEmpty()) {
            String mobilePhoneMod = mobilePhone.replaceAll("\\D+", "");

            String msg = this.mobileMsgTpl;
            msg = msg.replaceAll("%title%", contractTitle);
            msg = msg.replaceAll("%balance%", balance.toString());
            msg = msg.replaceAll("%result%", totalCost.subtract(balance).toString());

            String url = this.urlTpl;
            url = url.replaceAll("%mobile%", mobilePhoneMod);
            url = url.replaceAll("%message%", URLEncoder.encode(msg, "UTF-8"));

            sendSmsNotification(mobilePhoneMod, url, msg);
         }
      }
   }
}


Код:
package ru.provider.sms.tasks;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.List;

import bitel.billing.server.util.MailMsg;
import ru.bitel.bgbilling.kernel.task.server.TaskBase;

/**
 * <p>Основа для задач рассылки SMS и E-Mail уведомлений абонентам.</p>
 */
public abstract class AbstractSmsTask extends TaskBase {
   /**
    * <p>Идентификатор приложения для сбора статистики отправленных SMS</p>
    */
   protected String appId;

   protected int mode;
   protected long sleep;
   
   protected String tariffTotal;

   protected List<Integer> workGroups;
   protected List<Integer> skipGroups;

   protected int mobilePid;
   protected int emailPid;
   protected String urlTpl;
   protected String emailMsgTpl;
   protected String mobileMsgTpl;

   protected Connection con;

   @Override
   public String getDescription() {
      return this.defaultDescription;
   }
   
   @Override
   public boolean initTask() {
      this.appId = this.taskSetup.get("appId", "");

      this.mode = this.taskSetup.getInt("mode", 0);
      this.sleep = this.taskSetup.getLong("sleep", 0);
      
      this.tariffTotal = this.taskSetup.get("tariff.total", "");
      
      this.workGroups = this.taskSetup.getIntegerList("group.ids", new LinkedList<Integer>());
      this.skipGroups = this.taskSetup.getIntegerList("skip.ids", new LinkedList<Integer>());

      this.mobilePid = this.taskSetup.getInt("mobile.pid", 0);
      this.emailPid = this.taskSetup.getInt("email.pid", 0);

      this.urlTpl = this.taskSetup.get("url.tpl", "");
      this.emailMsgTpl = this.taskSetup.get("email.msg.tpl", "");
      this.mobileMsgTpl = this.taskSetup.get("mobile.msg.tpl", "");

      if (this.appId.isEmpty( )|| this.workGroups.isEmpty() || this.emailMsgTpl.isEmpty() || this.mobileMsgTpl.isEmpty() || this.urlTpl.isEmpty() || this.mobilePid == 0 || this.emailPid == 0) {
         return false;
      }

      return true;
    }

   @Override
   public abstract void executeTask();

   /**
    * <p>Отправка уведомления на электронную почту</p>
    * @param address Адрес электронной почты
    * @param title Заголовок сообщения
    * @param message Текст уведомления
    * @throws UnsupportedEncodingException
    */
   public void sendEmailNotification(String address, String title, String message) throws UnsupportedEncodingException {
      if (this.mode == 0) {
         return;
      }

      this.log.info("    E-Mail Address: " + address);
      this.log.info("    E-Mail Text:    " + message);

      MailMsg emailMsg = new MailMsg(this.setup);

      emailMsg.sendMessage(address, title, message);
   }

   /**
    * <p>Отправка уведомления через SMS</p>
    * <p>При успешной отправке сообщения по HTTP обновляет счётчит отправленных сообщений для статистики.</p>
    * @param mobile Номер телефона в формате 9XXXXXXXXX
    * @param url Адрес сервера для отправки запроса
    * @param message Текст уведомления
    * @throws UnsupportedEncodingException
    */
   public void sendSmsNotification(String mobile, String url, String message) throws UnsupportedEncodingException {
      if (this.mode == 0) {
         return;
      }

      this.log.info("    SMS Phone: " + mobile);
      this.log.info("    SMS Text:  " + message);
      this.log.info("    SMS URL:   " + url);

      URLConnection conn;
      try {
         conn = new URL(url).openConnection();
      } catch (MalformedURLException e) {
         this.log.error("Malformed URL found: url=" + url);
         this.log.error(e.getMessage());
         return;
      } catch (IOException e) {
         this.log.error("IOException while opening the url connection found:");
         this.log.error(e.getMessage());
         return;
      }

      String reply;
      try {
         reply = readStreamToString(conn.getInputStream(), "UTF-8");
      } catch (IOException e) {
         this.log.error("IOException while reading reply found:");
         this.log.error(e.getMessage());
         return;
      }

      this.log.info("    SMS Result: " + reply);

      if (reply.matches("^\\s*OK\\s*$")) {
         int messages = 0;
         if (message.length() <= 70) {
            messages = 1;
         } else {
            messages = (int)Math.ceil((float)message.length()/67);
         }

         try {
            Calendar today = Calendar.getInstance();
            PreparedStatement ps = this.con.prepareStatement("" +
                  " INSERT INTO" +
                  "   sms_stats" +
                  " VALUES (" +
                  "   ?," +
                  "   ?," +
                  "   ?," +
                  "   ?" +
                  " ) ON DUPLICATE KEY UPDATE messagesSend = messagesSend + ?");
            ps.setInt(1, today.get(Calendar.MONTH) + 1);
            ps.setInt(2, today.get(Calendar.YEAR) - 2000);
            ps.setString(3, appId);
            ps.setInt(4, messages);
            ps.setInt(5, messages);
            ps.execute();
            ps.close();
         } catch (SQLException e) {
            this.log.error("Cannot update SMS stats: " + e.getMessage());
         }
      }
   }

   /**
    * <p>Читает данные из потока и записывает их в выходную строку в соответствии с заданной кодировкой.</p>
    * @param in Входной поток
    * @param encoding Кодировка
    * @return
    * @throws IOException
    */
   public String readStreamToString(InputStream in, String encoding) throws IOException {
      StringBuffer b = new StringBuffer();
      InputStreamReader r = new InputStreamReader(in, encoding);
      int c;
      while ((c = r.read()) != -1) {
         b.append((char)c);
      }
      return b.toString();
   }

   /**
    * <p>Приостанавливает выполнение потока на заданное количество секунд.</p>
    * @throws InterruptedException
    */
   public void sleep() throws InterruptedException {
      if (sleep > 0) {
         Thread.sleep(sleep);
      }
   }
}


Конфиг задачи в биллинге:
Код:
# Режим запуска:
#   0 - сообщения не рассылаются, только запись логов работы
#   1 - сообщения рассылаются
mode=1
# Идентификатор приложения для сбора статистики по отправленным SMS-сообщениям
appId=NOTIFICATION
# Время ожидания в милисекундах после обработки одного абонента. 0 - нет ожидания.
sleep=1200
# Код модуля абонплат
npay.mid=2
# Группы договоров, которым рассылать уведомления. Для отправки уведомления у договора должны быть установлены все перечисленные группы одновременно!
group.ids=1,2
# Группы договоров, которым запрещено рассылать уведомления. Для исключения из рассылки у договора должна быть установлена хотя бы одна из перечисленных групп.
skip.ids=3
# Тарифные планы с подневной абонплатой
tariff.total=1,3,4
# Параметр договора, в котором содержится адрес электронной почты
email.pid=1
# Шаблон для отправки электронной почты
email.msg.tpl=Напоминаем пополнить счет на сумму %result% руб. по договору %title%.
# Параметр договора, в котором содержится номер мобильного телефона
mobile.pid=2
# Шаблон SMS сообщения
mobile.msg.tpl=Пополните счет на сумму %result% руб. по договору %title%.
# Шаблон адреса для отправки SMS
url.tpl=http://www.xxx.ru/send.php?phone=%mobile%&message=%message%


В базе нужно добавить:
Код:
SELECT * FROM bgbilling.scheduled_class;
1   Рассылка SMS уведомлений   ru.provider.sms.tasks.PeriodicSmsNotifications


Небольшие пояснения.
Задача проверяет, хватает ли денег на следующий месяц, сравнивая планируемую наработку из Calculator с балансом.
Если не хватает, то оправляется SMS и Email сообщения, если указаны номер телефона и/или адрес почты.
Задержка sleep нужна, чтобы звонки абонентов размазать по времени на весь рабочий день.
Для запуска классы нужно скомпилировать, собрать из них jar, положить рядом с kernel.jar. Перезапустить биллинг и планировщик. Добавить в базу одну строчку с новой задачей. Добавить через стандартный интерфейс новую задачу.
Не забываем обращать внимание на версию биллинга.

Из дополнительного здесь ведётся статистика отправленных сообщения для сверки счетов.

_________________

Клиент: вер. 6.2.873 / 04.12.2017 19:38:11
os: Windows 7; java: Java HotSpot(TM) 64-Bit Server VM, v.1.8.0_65
Сервер: вер. 6.2.1202 / 04.12.2017 19:39:21
os: Linux; java: Java HotSpot(TM) 64-Bit Server VM, v.1.8.0_91


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 12 май 2014, 17:20 
Не в сети
Клиент
Аватара пользователя

Зарегистрирован: 03 авг 2009, 18:42
Сообщения: 7166
Откуда: Благовещенск
Карма: 241
ох ёжик ))))))))) чета много букофф, а он для любой абонки подходит? что будет после обновления?

_________________
Код:
  Клиент: вер. 6.2.714 / 25.05.2015 17:27:15
    os: Linux; java: Java HotSpot(TM) 64-Bit Server VM, v.1.8.0_45
  Сервер: вер. 6.2.881 / 22.05.2015 17:56:55
    os: Linux; java: Java HotSpot(TM) 64-Bit Server VM, v.1.8.0_45
Помощь по администрированию bgbilling в jabber конференции или Группа в telegram
Стиль программирования - пьяный мастерстер
Разработка мобильных приложений


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 12 май 2014, 17:40 
Не в сети
Клиент

Зарегистрирован: 07 мар 2012, 15:02
Сообщения: 932
Откуда: Воронеж
Карма: 35
Что значит "для любой абонки"? Точно работает с ежемесячной абонплатой, учитывает опции. Абоненты с подневной абонплатой исключаются из рассылки. Для нас, собственно, имеет значение только ежемесячная абонплата.

После обновления, возможно, работать не будет. Но это всё я привёл для примера, как и просили, под себя всё-равно допиливать.

_________________

Клиент: вер. 6.2.873 / 04.12.2017 19:38:11
os: Windows 7; java: Java HotSpot(TM) 64-Bit Server VM, v.1.8.0_65
Сервер: вер. 6.2.1202 / 04.12.2017 19:39:21
os: Linux; java: Java HotSpot(TM) 64-Bit Server VM, v.1.8.0_91


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 12 май 2014, 18:00 
Не в сети
Клиент
Аватара пользователя

Зарегистрирован: 03 авг 2009, 18:42
Сообщения: 7166
Откуда: Благовещенск
Карма: 241
Ну да, я имел ввиду что лучше выложить в вику и с коментами как работает, чтоб по сообщениям не собирать

_________________
Код:
  Клиент: вер. 6.2.714 / 25.05.2015 17:27:15
    os: Linux; java: Java HotSpot(TM) 64-Bit Server VM, v.1.8.0_45
  Сервер: вер. 6.2.881 / 22.05.2015 17:56:55
    os: Linux; java: Java HotSpot(TM) 64-Bit Server VM, v.1.8.0_45
Помощь по администрированию bgbilling в jabber конференции или Группа в telegram
Стиль программирования - пьяный мастерстер
Разработка мобильных приложений


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 12 май 2014, 19:36 
Не в сети
Клиент

Зарегистрирован: 07 мар 2012, 15:02
Сообщения: 932
Откуда: Воронеж
Карма: 35
Попробую на досуге заняться.

_________________

Клиент: вер. 6.2.873 / 04.12.2017 19:38:11
os: Windows 7; java: Java HotSpot(TM) 64-Bit Server VM, v.1.8.0_65
Сервер: вер. 6.2.1202 / 04.12.2017 19:39:21
os: Linux; java: Java HotSpot(TM) 64-Bit Server VM, v.1.8.0_91


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 16 ] 

Часовой пояс: UTC + 5 часов [ Летнее время ]


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
POWERED_BY
Русская поддержка phpBB
[ Time : 0.051s | 44 Queries | GZIP : On ]