Pull to refresh

Как я делал свой учет финансов под андроид с блэкджеком, СМС и ФНС

Reading time 9 min
Views 45K

Введение


Все началось в далеком 2011-м году, когда я купил свой первый андроид смартфон и открыл для себя удивительный мир андроид маркета. Именно там я нашел великолепное приложение для учета финансов Financisto. Несколько лет я трекал в нем свои расходы и доходы, сильно привык, однако были и слабые стороны:


  • необходимость вводить все транзакции вручную. Притом, что доля безналичных платежей непреклонно росла, а банк на каждый чих шлет вам смс.
  • нет глобального взгляда на бюджет в длительном временном разрезе. То есть хотелось видеть таблицу, предположим, на год, где для каждого месяца было бы видно, сколько планировалось потратить и заработать и сколько вышло по факту, плюс итого по всем строкам и столбцам. Тут ориентиром был YNAB.
  • нет синхронизации между устройствами. Да был Flowzr, но как-то он мне не зашел.

Если вторая проблема решилась экспортом в CSV и всемогущим экселем, то с остальными нужно было что-то делать. Очевидный вариант — сменить программу. Поизучав предложение, пришел к выводу, что все приложения делятся на скудные по функционалу и на дорогие:) Тем временем шел 2015-й год и мне все сильнее хотелось изучить разработку под мобильные девайсы. Что ж, звезды сходятся, принято решение пилить свое приложение!


Так как мой девелоперский бэкграунд был связан с написанием узкоспециализированных программ на дельфи, то, естественно, первым порывом было попробовать мультиплатформенную разработку в самой дельфи. Но не будем о том печальном опыте, я быстро пришел к выводу, что мне нужно нативное приложение и нормальный тулинг. Так была скачана андроид студия и создан новый проект. Далее идет мой поток сознания, который я постарался разделить по темам.




О приложении


Приложение имеет 2 основополагающие сущности: счета и транзакции. Счет, это хранилище средств, транзакция — перемещение средств. Транзакции бывают трех видов:


  • приход — пополнение счета третьими лицами
  • расход — выплата наших средств третьим лицам
  • перевод — перевод средств между своими счетами

Собственно в этом вся концепция приложения. Далее опишу, что фактически было реализовано. Некоторые моменты опишу подробно ниже.


Итак, первое, что нужно для упрощения жизни, это парсинг смс от банков для автоматического создания транзакций. Затем был сделан импорт/экспорт данных в CSV, причем предмет особой гордости — настраиваемый импорт, позволяющий загружать данные из файлов CSV произвольной структуры. Имеется сканер чеков ФНС РФ и загрузка информации по ним с сервера. Для удобного учета атрибуты транзакций сделаны многоуровневыми. Например, можно создать такое дерево категорий:


├ Расходы
│   ├ Автомобиль`
│   │   ├ Заправка
│   │   └ Обслуживание
│   ├ Еда
│   └ Развлечения
│
└ Доходы

Аналогичная структура возможна и у других атрибутов, таких как Получатели (контрагенты), Проекты и т.д. Для удобной навигации по данным сделана система фильтров, по различным признакам. Реализовано управление долгами и бюджетирование. Кроме того есть вагон и маленькая тележка более мелких функций, которые я перечислять тут не буду.


Библиотеки и тулинг


Из нестандартных используемых библиотек могу выделить ButterKnife и EventBus. Хотя в 2018 году они выглядят анахронизмами, на момент начала разработки они выглядели многообещающе. Сейчас же я не готов осуществить полномасштабный рефакторинг. Экспериментировал с RetroLambda и Rx, но выпилил их как не соответствующие задаче. В итоге сейчас проект это чистая Java 7, хотя велико желание поддаться хайпу и попробовать Kotlin.


Очень полезной оказалась библиотека io.requery:sqlite-android, позволяющая иметь всегда актуальную версию SQLite. В приложении реализованы деревья сущностей (например, вложенные категории) без ограничения по глубине и для выборки таких данных очень эффективно использовать рекурсивные запросы. К сожалению, они появились в достаточно свежих версиях SQLite и не доступны на старых версиях андроида. Requery решает эту задачу.


На данный момент в коде 39 внешних зависимостей. Да, это много, и я провожу планомерную работу по их уменьшению. Но, тем не менее, считаю, что использование сторонних библиотек эффективно при быстром наращивании функционала.


Очень хочется внедрить нормальный DI, но опять же пока нет на это времени.


Несколько слов о тулинге. Если в 2014-2015 еще можно было услышать о том, что разрабатывать нужно в Eclipse, а Genymotion был musthave для разработчика под андроид, то сегодня Гугл всех затмил. Android Studio очень быстра и удобна, впрочем как и встроенный эмулятор.


Так же хотелось бы сказать спасибо kaftanati за его инструмент. Он позволяет вести гугл-таблицу со строковыми ресурсами на разных языках и преобразовывать ее в xml-файлы. Очень упрощает процесс локализации. К слову на данный момент приложение доступно на 2-х языках: EN и RU.


В процессе разработки неплохо освоил Git, оказалась незаменимая вещь.


Производительность


Оптимизации производительности было уделено немало времени. Выделить следующие моменты, оказавшие значительное влияние:


  • Глубина вложенности лэйаутов. Чем меньше тем лучше. Проблема практически исчезла после внедрения constraint layout.
  • Оптимизация БД. Индексы наше все.
  • Профайлинг. TraceView это очень полезный инструмент для понимания того, что происходт в недрах приложения.

В целом сейчас я доволен производительностью. Моя личная база, которая является одновременно тестовой, содержит архив транзакций за 5 лет (>7000 транзакций) и при этом ничуть не тормозит на не самых быстрых телефонах.


Дизайн


Лично у меня с дизайном все плохо. Наверное поэтому первая версия получилась такой вырвиглазной. Однако при этом она более менее соответствовала нормам материального дизайна). Такая версия просуществовала около двух лет, когда наконец я понял, что нужно что-то менять. Так как опыт показывал, что сам я не справлюсь, то был брошен клич среди фрилансеров. Таковой достаточно быстро нашелся и за разумные деньги перерисовал мне все экраны. Результат я получил в psd, но так как я был уже наслышан о таком замечательном инструменте как Zeplin, то сам быстренько все в него экспортировал и переделал дизайн. Нынешний мне нравится гораздо больше, кроме того в процессе переработки сформировались некие внутренние гайлайны, так что теперь создание нового экрана не вызывает затруднений.


Было и стало:



Первая версия материального дизайна состояла, по-сути, из одних гайдайнов, с которыми разработчик оставался один на один. По-этому расплодилось множество библиотек, которые предлагали реализацию UI. Не обошла эта проблема и меня, в желании реализовать как можно ближе к эталону было импортировано много библиотек. Но Гугл исправляется и двигается в сторону единообразия и упрощения в процессе разработки. Современная версия support'а позволяет обойтись практически без сторонних компонентов.


Парсинг смс


Большинство приложений практикует парсинг смс по предустановленным форматам. То есть разработчик берет смс конкретного банка, пишет правила как его разбирать на части и вшивает в код. Бывает такие правила можно править пользователям, но это весьма замудренный процесс. Достоинства и недостатки такого подхода очевидны: если разработчик внедрил поддержку твоего банка, то все отлично и быстро работает. Однако, если банк вдруг решит поменять формат или ваш банк не известен разработчику, то все резко перестает работать. Я решил, что приложение ничего не должно знать о формате смс и возложить все на пользователя, постаравшись максимально облегчить ему задачу.


Итак общая концепция такова: вам приходит смс, например, следующего содержания: "VISA1234 01.01.18 12:00 покупка 106.40р SUPERMARKET Баланс: 6623.34р" (Сбербанк). Очевидно, что тут можно извлечь следующую информацию: номер карты (счет), дата и время, получатель средств, сумма транзакции и остаток средств на карте. Задача пользователя правильно расставить ключевые слова (маркеры): выделить "VISA1234" и поставить маркер счет, на "SUPERMARKET" поставить маркер Получатель и т.д.


Выглядит это примерно так:


Приложение запоминает все маркеры и таким образом обучается. Опыт показывает, что после недели-двух обучения, 90% транзакций создаются автоматически без участия пользователя. Да, нужно затратить некоторые усилия, но независимость от сторонних лиц мне кажется стоит того.


Пользователям тоже нравится, поступает очень много "хотелок", так, например были реализованы: импорт ранее пришедших смс, парсинг смс из буфера обмена и т.д.


Загрузка кассовых чеков ФНС


В прошлом году ФНС РФ преподнесла всем продавцам подарок обязав отправлять все кассовые чеки в электронном виде на свои сервера. Простым людям тоже маленько перепало в виде официального мобильного приложения, в котором можно проверить чек на подлинность и, что самое важно, загрузить его себе в форматах pdf или json. Не раз уже эта тема тут обсуждалась, однако, вкратце: официального апи для получения чека нет. Оно может быть у некоторых из ОФД (операторы фискальных данных, через которых чеки попадают с касс в ФНС), но так, что бы взять и получить любой чек в одном месте — нет. НО, есть официальное мобильное приложение, работающее через http, с обычной http-авторизацией, чем давно воспользовались добрые люди, послушавшие трафик и выложившие его апи на всеобщее обозрение. Там все просто. Можно создать нового пользователя, получив пароль по смс, можно скачать содержимое чека по его данным, и можно скачать все чеки за определенный период, ранее загруженные данным пользователем. Для облегчения задачи на каждом чеке печатается QR-код, содержащий все нужные для получения чека данные.


Далее все просто qrcodereaderview + retrofit и содержимое чека у нас в руках. В связи с возможностью загружать список товаров в чеке, была реализована возможность эти товары прикреплять к транзакции. То есть теперь у вас транзакция может быть не просто суммой, а составной суммой, например, товар1 х кол-во х стоимость + товар2 х кол-во х стоимость + ... Причем каждому товару можно назначить отдельную категорию и проект, что бывает очень полезно при покупках в супермаркетах, когда за один раз берется много разнородного товара.


Автоматизация


Одним из интересных запросов пользователей оказалось желание автоматизировать создание транзакций при помощи интентов, что собственно и было сделано. Можно в любом приложении создать интент с суммой, и атрибутами транзакции и послать его в мое приложение, после чего такая транзакция будет автоматически создана. Сам, честно говоря, такой метод не применяю, но есть люди, которые парсят emailы в таскере, а затем создают на их основе транзакции. Или еще вариант — создание транзакций голосом через Дусю.


К сожалению, пока есть проблемы на 8-ом андроиде, так как там запретили фоновое выполнение интентов. Планирую в ближайших версиях сделать запуск foreground-процесса тем пользователям, которые хотят такой функционал.


Синхронизация


Синхронизация, как много в этом слове… Ведение общей базы было одной из основных задач создания проекта. К сожалению, она до сих пор не реализована. Причина — слишком комплексная задача для пет-прожекта одного человека. Попытка была. И даже была рабочая версия. Сделал я ее на Firebase. На первый взгляд это выглядело не сложно. Есть гигантский json, в котором лежат общие базы. Вся аутентификация делается 10-ю строчками в правилах безопасности в консоли. Апи очень простое и удобное. Алгоритм был примерно следующий:


  1. Пользователь логинится в Realtime Database при помощи учетки Гугла.
  2. Ему заводится нода, в которую выгружается вся его база.
  3. Затем он дает разрешение на модификацию своей базы другим пользователям, так же по gmail'у.
  4. Другие пользователи, при подключении, указывают, что хотят работать с чужой базой и вводят адрес первого пользователя, затем подключаются к его ноде и могут добавлять удалять информацию.

Затем начались проблемы: как сделать разграничение прав доступа?; на больших базах были проблемы с производительностью; синхронизацию предполагалось предлагать в виде подписки, для этого нужна верификация на сервере, то есть опять же нужен бэкэнд. Конечно все эти проблемы были связаны с недостатком моего опыта и отсутствием времени на полномасштабное изучение вопроса, но пулей в голову данному подходу стало заявление Гугла о том, что relatime database, это теперь стремно, делайте ка все на Firestore. В общем пока эта затея поставлена на паузу, продолжаю изучать пути решения. На данный момент мне видятся следующие варианты реализации:


  • Попробовать все-таки Firestore, там ввели коллекции, упростилась работа со сложными структурами данных.
  • Плюнуть на все и сделать свой бэкенд. Пока что неплохим кандидатом выглядит Postgres + Postgrest. Минимум разработки, больше контроля, но опять же есть непонятные моменты.
  • Экзотический вариант — xmpp сервер. Вообще не хранить данные на сервере, а лишь пересылать их между пользователями. Чревато, на мой взгляд, потерей конситентности, но есть и плюсы (хотя как посмотреть) в виде полного отсутствия бэкенда.

В общем, мне был бы интересен ваш опыт решения данной задачи, может кто наставит на путь истинный.


Продвижение и заработок


Наверное самая слабая сторона моего проекта. К превеликому моему сожалению, разрабатывать мне гораздо интереснее чем продавать. Трафик исключительно органический. Проект представлен на 4PDA, там же сформировалась база лояльных пользователей. Значительно увеличила количество установок публикация, опять же на 4PDA, в рамках программы поддержки разработчиков. Могу сказать, что средства потраченные на нее окупились, но не более.


Изначально программа задумывалась как учебный проект, поэтому о заработке на ней речи не шло. Однако, in-app purchases тоже надо изучить, поэтому была добавлена концепция Pro-функций, то есть платных фич. Фича такая пока одна единственная — это возможность строить графические отчеты. Планировал сделать подписку на синхронизацию, но за неимением фичи, так и нет подписки.


GitHub


Длительное время я не мог решиться открыть исходники. Ну знаете, хакнут покупки, будут смеяться над кодом и т.д. Но потом пришло понимание, что открытый исходный код будет благом, поэтому он доступен по ссылке.


Заключение


Основная цель, которую я ставил перед собой начиная этот проект, выполнена — я научился андроиду. И, можно сказать, даже преуспел в этом. Для полноценного звания success story, конечно, не хватает коммерческого успеха, но, тем не менее, я рад, что мне удалось развить проект и довести его до ума. Греет мысль и о том, что дело делаю полезное для людей.

Tags:
Hubs:
+44
Comments 67
Comments Comments 67

Articles