Разработка мобильного приложения "Smarty CRM"
Теоретические аспекты использования CRM-систем для повышения эффективности бизнеса. Разработка программно-информационного компонента. Обоснование выбора среды разработки. Описание пользовательского интерфейса и программных модулей, разработка приложения.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | курсовая работа |
Язык | русский |
Дата добавления | 13.10.2016 |
Размер файла | 2,1 M |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru//
Размещено на http://www.allbest.ru//
Введение
приложение информационный интерфейс
Часто можно услышать от руководителей компаний о уменьшении объема заказов, упадке продаж, заморозке проектов. Для многих организаций стала актуальной тема сокращения. «Легкие деньги» и достаточное количество потребителей, к которым за годы роста экономики привыкло большинство компаний, кончились.
В таких условиях организациям продавать услуги и товары, а также удерживать потребителей стало сложнее. Клиенты стали внимательнее считать деньги, экономить и торговаться. Спрос покупателей перемещается в сторону наиболее дешевых предложений, потребители отказываются от необязательного и дополнительного, сопутствующих услуг и товаров. Конкуренция усиливается на зарубежных рынках внутри страны.
В нынешних условиях организациям нужно изменить тактику работы. Важнейшими проблемами, с которыми уже столкнулись или могут столкнуться предприятия, являются упадок спроса на услуги и товары, уход потребителей, понижение прибыли. Из-за этого одними из важнейших задач владельца становятся сохранение потребителей, понижение затрат и увеличение эффективности процессов организации. Тактику быстрого роста и активного освоения рынка обязаны изменить экономию (срезание затрат) и повысить эффективность каждой операции важных процессов компании.
«Инновации» на данный момент на слуху, в России начинает строиться инновационная экономика. Но по оценкам руководителей правительства производительность труда в компаниях хуже, чем у аналогов зарубежных компаниях более чем в 5 раз, а услуги и товары имеют выше себестоимость по сравнению с зарубежными. При этих оценках эффективности компании, возможно, не смогут быть конкурентоспособными с представителями зарубежного бизнеса.
Стратегией успешного дальнейшего развития и существования современных компаний становится управление с более высокой эффективностью взаимоотношений с потребителями. Направленность организаций на улучшение взаимоотношений с потребителями обусловлена несколькими тенденций, в частности увеличением конкуренции, увеличением требований покупателей к уровню сервиса и качеству продуктов, понижением эффективности традиционных средств, и появление новейших технологий взаимодействия с потребителями и функционирования филиалов организации. Хорошее знание своих потребителей и удовлетворение запросов и потребностей каждого из них могут позволить организации получить возможности для сбыта услуг и товаров и стать важнейшим фактором развития и источником конкурентного преимущества компании. Лазарева Н. CRM: едкий вкус конкуренции / ИТ-Бизнес CRN [Электронный ресурс]
Зарубежный опыт выявляет, что наибольшая эффективность работы с потребителями обеспечивается с помощью принятия организацией концепции по управлению отношениями с потребителями, называющаяся CRM (Customer Relationship Management).
CRM-концепция дает интегрировать потребителя в сферу организации - компания получает максимальную информацию о своих потребителях и их потребностях и, изучив эти данные, строит свою стратегию, которая касается аспектов ее деятельности такие как: обслуживания, производства, продаж и маркетинга.
В ситуации кризиса и глобализации экономики, CRM является для бизнеса важнейшей инновацией в управлении. Если в 2000 году с CRM работало 35% компаний, то за несколько лет популярность CRM возросла более чем в два раза. Сегодня CRM используют 75% владельцев. Оганесян А. CRM-витамины в России принимают сквозь слезы / Cnews [Электронный ресурс]
Рост популярности CRM в мире отражают тенденции такие как:
большее значение, которое разработчики CRM придают потребностям своих пользователей;
более четкое понимание как применять и создавать CRM в компании.
Рынок CRM растет по оценкам на 40% в год и быстро приближается к цифре в 100 млн. долларов. И мировой финансовый кризис не помеха, а скорее возможность организациям с помощью CRM сделать бизнес более эффективным.
В связи с этим, целью моей работы является разработка мобильного приложения SmartyCRM под мобильную платформу IOS. Для достижения данной цели ставиться несколько задач:
Познакомиться с теоретические аспекты использования CRM-систем для повышения эффективности бизнеса
Изучить принципы разработки под мобильную платформу IOS.
Изучить новый язык программирования swift.
1. Теоретические аспекты использования CRM
1.1 Понятие CRM, ее роль и функции в увеличении эффективности деятельности организации
CRM - это клиентоориентированная технология, собравшая в себе большое количество эффективных инструментов, дающих возможность значительно увеличить эффективность работы организации.
CRM - стратегия использующая передовые управленческие и информационные технологии, которые позволяют организации выстраивать выгодные отношения со своими потребителями. В результате применения клиентоориентированной стратегии повышениется способность компании к конкуренции и повышение прибыли.
Сама аббревиатура CRM (Customers Relationship Management - управление отношениями с потребителями) стала набирать популярность с середины 90 годов 20 века. Предназначение CRM сказал Томас Давенпорт, профессор университета из Бостона и управляющий Института стратегических перемен. Во-первых, с увеличением глобальной конкуренции и понижением отличий в качестве одинаковых услуг и товаров компании меняют свою стратегию с продуктоориентированной на клиентоориентированную. Во-вторых, развитие технологий позволяет собирать и изучать данные о потребителях вне зависимости от количества, сделало возможным рост клиентоориентированных технологий в масштабах организаций.
Концепция CRM не изобретение последнего времени и использовались очень давно. Простейшие CRM прошлого в виде амбарных, писцовых, долговых книг часто давали не только вспомнить историю взаимоотношений с потребителями, но и проявить по отношению к потребителю больше внимания, а также дать понять, что взаимоотношения не забыты. Это уже давало сохранить постоянных потребителей и привлечь новых.
Этот подход, позднее, в первую очередь улучшался в сфере сервиса и услуг, более значительно в малом бизнесе. CRM так же называют технологией дешевого роста, потому что она доступна и имеет значительный эффект для компании. Именно клиентоориентированность давала предприятиям малого бизнеса выйти из ценовой конкуренции с крупными корпорациями, сохранять потребителей и повышать продажи.
Первая программа для управления контактами, называющаяся «ACT!», была сделана в 1987 году. А сам термин CRM был использован Siebel Systems, чтобы выразить специфику типа корпоративных программных продуктов. Сейчас в мире существует более тысячи решений, которые относят к классу CRM. Андерсон К. Менеджмент, ориентированный на потребителя: CRM-технологии как основа новых отношений с клиентом / М.: Гранд-Фаир, 2003.
Первые проекты внедрения CRM в России были сделаны еще в 80 - 90 годы. В то время внедрения выполнялись в основном в финансовом секторе, потому что позволить себе тогда зарубежную CRM и зарубежных консультантов могла не каждая компания.
Несмотря на это CRM есть на рынке более 20 лет, вопрос о функциональных составляющих все еще не закрыт. Хотя определение CRM развивается, многие специалисты cчитают, что современное CRM должно иметь 11 важных частей такие как:
управление контактами;
управление продажами;
продажи по телефону;
управление временем;
поддержка и обслуживание потребителей;
управление маркетингом;
отчетность для высшего руководства;
интеграция с другими системами;
синхронизация данных;
управление электронной торговлей;
управление мобильными продажами.
В современном CRM также обязаны быть сделано возможности управления процессами и компьютерная телефония, ставшие неотъемлемой частью.
Основная цель внедрения CRM - это повышение объема прибыли и продаж. CRM позволяет построить систему управления продажами, повысить лояльность потребителей и увеличить объем продаж.
Лояльность, приверженность потребителя к компании важная составляющая CRM. Лояльный потребитель - это постоянный потребитель, ему нравится продукция и сервис, оказываемый в компании. Именно лояльный потребитель - приносит постоянный доход компании, поддерживает положительный имидж компании, привлекает новых потребителей.
Лояльность достигается тем, что компания предоставляет потребителю не только качественную продукцию и сервис, но и идет на встречу его личным интересам (персонализация потребителя).
СRМ необходимы организациям, которые хотят построить эффективную систему управления продажами и у которых потребитель - единственный источник дохода компании. Новые технологии CRM в работе отдела продаж, маркетинга и сервиса являются залогом благосостояния компании. Также CRM необходимы организациям, работающим на рынке с высокой конкуренцией, т.к. повышение лояльности потребителей - это дополнительный рычаг в конкурентной борьбе.
Повышение лояльности позволяет увеличить число постоянных потребителей, количество повторных покупок, снизить затраты на привлечение новых потребителей.
CRM помогает поддерживать контакты одновременно со многими потребителями, не забывать про них, поэтому такие системы особенно актуальны в компаниях с большим количеством потребителей. Гринберг Пол. CRM со скоростью света. Привлечение и удержание клиентов в реальном времени через Интернет - М.: Символ-Плюс, 2006.
Наконец, CRM будут полезны в организациях, у которых процесс продажи растянут во времени, и включает несколько этапов, например, поиск и привлечение потребителя, презентация товара, подготовка и согласование параметров сделки, договора, оплата и поставка товара, гарантийное обслуживание и др.
1.2 Основные типы CRM
Оперативная CRM
Оперативный CRM -- это уровень автоматизации оперативных процедур исполнителей и оперативных руководителей разного уровня. В России именно информационные системы этого уровня чаще всего называют CRM. К данному слою относятся (фронт-офисные) системы автоматизации маркетинга, продаж и сервиса; системы интеграции фронт-офисных и учетных подсистем; собственно, учетные системы, хранящие и обрабатывающие финансовую информацию о потребителях. Потребителями результатов автоматизации данного уровня являются непосредственные исполнители -- сотрудники отделов, работающих с потребителями: маркетологи, менеджеры по продажам, секретари, руководители соответствующих линейных подразделений, коммерческий директорат, служба сервисной поддержки.
Аналитическая CRM
Аналитический CRM -- это уровень автоматизации управленческих процессов, связанных с глубоким анализом данных о потребительской базе компании. Соответственно, информационные системы, входящие в этот слой, -- это системы организации хранилищ данных, системы оперативного и статистического анализа (OLAP, в частности) постребительской базы. Потребителями результатов автоматизации данного уровня являются чаще всего руководители, занимающиеся стратегическим управлением компании.
В число задач, решаемых с помощью аналитического CRM, входят синхронизация разрозненных массивов данных и поиск статистических закономерностей в этих данных для выработки наиболее эффективной стратегии маркетинга, продаж, обслуживания потребителей и т.п. Требует хорошей интеграции систем, большого объема наработанных статистических данных, качественного аналитического инструментария.
Аналитический CRM менее популярен, чем оперативный. Однако он больше связан с BI-системами, а также соприкасается с концепциями Data Warehousing, Data mining - об интеллектуальном анализе данных, поэтому поставщики систем в этих областях активно продвигают и репозиционируют свои системы как системы Аналитического CRM (например, SAS).
Коллаборационная CRM
Коллаборационный CRM -- это уровень автоматизации контактов с потребителями по различным каналам связи (телефон, личный контакт, электронные каналы). Этот слой информационных систем компании может состоять из веб-портала (электронный канал -- интернет), системы электронной почты (тоже интернет), call-центра (телефонный канал), системы учета и планирования контактов (личные контакты). Потребителями результата автоматизации этого уровня являются те же сотрудники, что и в слое оперативного СRМ.
Систем, поддерживающих коллаборационный CRM, практически нет на рынке, в том числе потому, что коллаборационный процесс в большинстве случаев сугубо индивидуален и должен автоматизироваться за счет чрезвычайно гибкой CRM. Кроме того, эта система должна быть основана на самых дешевых и открытых технологиях снижения затрат на построение интерфейса между вашей организацией и вашими потребителями.
Sales Intelligence CRM
Разрабатываются на основе аналитических CRM систем. Их преимуществами являются возможности проведения различных вариантов продаж: перекрестных, дополняющих, подменяющих. Кроме того, система дает представление о характеристиках реализации товаров, потребитель обороте, прибыли компании с конкретного потребителя, результатах сравнения потребителей, входящих в состав целевой группы.
СRM для управления к0мпаниями
Они представляют собой комбинацию оперативных и аналитических систем. Они позволяют выделять целевые группы, а также осуществлять двустороннюю связь с потребителями посредством рассылки сообщений рекламного характера и различных информационных материалов. Для этого используются различные каналы: традиционная и электронная почта, телефонная связь, SMS. Системы выполняют функции хранения и обработки результатов проведенных акций. С их помощью создаются статистические базы данных.
2.Разработка программно-информационного компонента. Обоснование выбора среды разработки
Проанализировав результаты логического проектирования, нужно определить методы решения поставленных задач.
Основные требования сводятся к следующему:
1) система должна быть надежной;
2) не должна нарушаться целостность данных при внесении изменений;
3) система должна обеспечивать дружественный интуитивный интерфейс, удобное перемещение и быстрый вызов любой функции;
4) должна включать в себя помощь и подсказки по эксплуатации;
5)должна поддерживаться на устройства с операционной системой IOS 8 и выше
В силу специфики разрабатываемой системы и среды ее эксплуатации мы можем рассматривать средства, применяемые при создании мобильных приложений.
2.1 Среда разработки
- XCode - интегрированная среда разработки программного обеспечения под OS X и iOS, разработанная корпорацией Apple. Первая версия выпущена в 2001 году. Стабильные версии распространяется бесплатно через Mac App Store. Зарегистрированные разработчики также имеют доступ к бета-сборкам через сайт Apple.
- AppCode - полнофункциональная IDE для iOS/OS X разработчиков, которая помогает им с легкостью и удовольствием создавать выдающиеся приложения для устройств Apple, таких как Mac, iPhone и iPad.
Таким образом, я выбрал xCode, так как можно избежать посредников при разработке, так как при компиляции в AppCode вызывается компилятор xCode и строиться приложение по новой.
2.2. Язык программирования
- Objective C-компилируемый объектно-ориентированный язык программирования, используемый корпорацией Apple, построенный на основе языка Си и парадигм Smalltalk. В частности, объектная модель построена в стиле Smalltalk -- то есть объектам посылаются сообщения.
- Swift -- открытый мультипарадигменный объектно-ориентированный язык программирования общего назначения. Создан компанией Apple в первую очередь для разработчиков iOS и OS X. Swift работает с фреймворками Cocoa и Cocoa Touch и совместим с основной кодовой базой Apple, написанной на Objective-C. Swift задумывался как более безопасный язык в сравнении с Objective-C. Программы на нем компилируются при помощи LLVM, входящего в интегрированную среду разработкиXcode 6 и выше. Swift может использовать рантаймObjective-C, что делает возможным использование обоих языков (а также С) в рамках одной программы. Был анонсирован на конференции разработчиков WWDC 2014.
Таким образом, я выбрал Swift, так как это новый язык и более безопасный, чем Objective C.
2.3 База данных
CoreData - гибкий фрэймворк для работы с хранимыми на устройстве данными предоставленный компанией Apple.
Realm -- кроссплатформенная мобильная база данных для iOS (доступная в Swift & Objective-C) и Android. Realm была создана, чтобы стать лучше и быстрее, чем SQLite и Core Data. Она не только лучше и быстрее, но и простая в использовании, так вы можете сделать многое с помощью всего нескольких строк кода. Realm является совершенно бесплатной, и вы можете использовать ее без каких-либо ограничений. Realm создана для мобильных приложений, и это новинка, так как в последнее десятилетие, мы не замечали инноваций в мобильных базах данных. Теперь, чтобы работать с мобильной базой данных, у вас есть только один вариант, который является SQLite или любой оберткой, которая использует SQLite. Realm разработана, чтобы быть простой в использовании, так как она не ORM, и она использует свой собственный механизм персистентности для большей производительности и скорости выполнения.
SQLite - этореляционная база данных, запросы к которой можно осуществлять при помощи языка запросов SQL. База данных не поддерживает все особенности SQL и уступает в функциональности другим развитым СУБД, но вполне подходит для хранения и извлечения информации.
Таким образом, я выбрал Realm, лучше и быстрее, чем SQLite и Core Data, также она простая в использовании, так вы можете сделать многое с помощью всего нескольких строк кода.
3.Разработка приложения
3.1 Физическая модель данных
Физическая модель данных определяет то, как размещены данные в системе, как получить к ним доступ, как проиндексированы данные. Физическая модель данных называется внутренней моделью системы. Она отличается от других моделей данных способом представления взаимосвязей между объектами системы и тем, на каком уровне эти объекты рассматриваются. Концептуальная модель дает общее представление о том, какие данные функционируют в системе и как они связаны с материальным миром и между собой, не вдаваясь ни в подробности хранения, ни в подробности хранения, структуризации и представления данных в системе. Логическая модель представляет взаимодействие данных в виде сущностей с наборами атрибутов, однако не рассматривает физическое представление этих данных. Физическая же модель по сути отражает реальное положение вещей - каким образом программист решил перевести концептуальную и логическую модель в набор таблиц, связанных реляционными отношениями с помощью ключей и заполненных теми данными, что согласно концептуальной модели присутствуют в данной системе или классе систем.
Таблица 1 - Пользователь (User)
Поле |
Тип |
Описание |
|
_id |
Int |
Уникальный номер пользователя |
|
name |
String |
Имя пользователя |
|
Url |
String |
Адрес автарки |
|
Position |
String |
Позиция занимаемая пользователем в компании |
|
limit |
Int |
Поле определяющее количество доступных контактов |
|
country |
String |
Страна в которой находиться пользователь |
|
city |
String |
Город в котором находиться пользователь |
Таблица 2 - Контакт(contact)
Поле |
Тип |
Описание |
|
_id |
Int |
Уникальный номер пользователя |
|
name |
String |
Имя пользователя |
|
phone |
String |
Номер телефона контакта |
|
|
String |
Электронный адрес контакта |
|
isOrganization |
Int |
Поле определяющее тип контакта (человек или целая организация) |
|
type |
Int |
Поле определяющее тип контакта (новый, старый, действующий) |
|
isArchive |
Int |
Поле определяющее находится ли контакт в архиве |
|
chats |
Object |
Чаты с этим контактом |
|
updatedOn |
Int |
Момент обновления контакта(Unix time stamp) |
|
createdOn |
Int |
Момент созданиия контакта(Unix time stamp) |
|
country |
String |
Страна в которой находиться контакт |
|
city |
String |
Город в котором находиться контакт |
Таблица 3 - Заметка(note)
Поле |
Тип |
Описание |
|
_id |
Int |
Уникальный номер заметки |
|
title |
String |
Название заметки |
|
description |
String |
Описание заметки |
|
updatedOn |
Int |
Момент обновления контакта (Unix time stamp) |
|
createdOn |
Int |
Момент созданиия контакта (Unix time stamp) |
Таблица 4 - Задача(task)
Поле |
Тип |
Описание |
|
_id |
Int |
Уникальный номер заметки |
|
title |
String |
Название заметки |
|
description |
String |
Описание заметки |
|
isAchive |
String |
Выполнена ли задача |
|
updatedOn |
Int |
Момент обновления контакта (Unix time stamp) |
|
createdOn |
Int |
Момент созданиия контакта (Unix time stamp) |
Таблица 5 - Цель(goal)
Поле |
Тип |
Описание |
|
_id |
Int |
Уникальный номер заметки |
|
title |
String |
Название заметки |
|
description |
String |
Описание заметки |
|
parent |
Int |
Уникальный родителя цели |
|
progress |
Int |
На каком этапе выполнения находиться цель в процентном соотношении |
|
updatedOn |
Int |
Момент обновления контакта (Unix time stamp) |
|
createdOn |
Int |
Момент созданиия контакта (Unix time stamp) |
3.2 Описание пользовательского интерфейса и программных модулей
При разработке пользовательского интерфейса нужно учитывать следующие требования:
интерфейс должен быть максимально удобен и интуитивно прост;
пользователь должен иметь «под рукой» все необходимые средства для типовой работы с данными;
информация должна в зависимости от выполняемых задач разбита на логические подгруппы в пределах одной формы (так, кнопки «назад» и «вперед» обязаны размещаться рядом)
информации не должно быть слишком много, чтобы в ней было легко ориентироваться;
для визуального оформления и эстетически приятного восприятия информации следует вводить графические элементы - фоновые картинки и прочую графику, использовать различные шрифты;
однако шрифтами не стоит злоупотреблять - следует избегать убористого текста, вычурных и трудночитаемых начертаний, цветов, которые плохо воспринимаются, сильного различия в размерах шрифтов в пределах одной формы (желательно в пределах всего проекта).
Исходя из этих требований, нужно создавать интерфейс программы. Когда проектирование интерфейса и компоновки элементов закончено, идет собственно верстка, когда при помощи средств фреймверка snapKit создается законченный интерфейс. После отладки макета верстки в различных разрешениях идет собственно написание программного кода продукта, его отладка и выдача окончательного варианта в виде совокупности сверстанных страниц и результатов выполнения исходного кода.
При входе в систему пользователь видит перед собой форму авторизации. Пользователь может ввести данные в поля ввода и войти в систему под своим аккаунтом. Если у него еще нет учетной записи, то он может зарегистрироваться в системе. При следующем входе в систему пользователю не нужно будет их вводить заново. После захода в приложение пользователь увидит раздел контакты показанный на рисунке 1.
Рисунок 1.
Нажав на боковую кнопку в верхней панели либо сдвинув экран влево пользователь увидит боков меня в котором, он сможет передвигаться по разделам, как показано на рисунке 2.
Рисунок 2.
Так же при выборе контакта пользователь сможет просмотреть данные соответствующего контакта и отредактировать их, как показано на рисунке 3.
Рисунок 3.
При переходе в какой-либо раздел пользователь должен увидеть соответствующий раздел на экране как указано на рисунках 4 и 5. Примером служат скриншоты разделов задачи.
Рисунок 4. Рисунок 5.
Заключение
В данной дипломной работе была рассмотрена проблема предпринимательства. В наше время очень сложно удержать клиентов и быть конкурентоспособным на рынке во время кризиса.
Проанализировав эту ситуацию был сделан вывод о необходимости создания СRMсистемы, которое поможет предпринимателям стать ближе к своим покупателям и поддерживать с ними взаимоотношения и как следствие сохранить на долгое время.
Мобильное приложение было создано на основе существующей модели CRMсистемы, дабы привлечь большее количество пользователей.
Мобильное приложение «SmartyCRM» предоставляет пользователям огромный возможности для управления своими данными, не ограничивая их при этом. Приложение дает возможность базу контактов и управлять ей как ему заблагорассудиться. Так же он может вести переписки с этим контактом. Одним аккаунтом может пользоваться вся компания. Еще пользователь может создавать заметки и прикреплять их к контактам, так будет проще вспомнить что это за клиент и на каком этапе взаимоотношений вы находитесь. Так же пользователь может создавать задачи её так же можно прикреплять к контакту и отмечать выполненные и не выполненные это поможет руководителю видеть выполнена ли данная задача по какому-либо клиенту. Еще одной замечательной особенностью будет создание целей, которых должен достичь сотрудник. Так же он может выставлять прогресс по выполнению этих целей. И самая главная особенность совместная работа в которой один пользователь может заходить в аккаунты других пользователей если ему откроют доступ к аккаунту. Это поможет руководителю проследить за прогрессом и выполнением работ.
Реализованное приложение «Smarty CRM» соответствует всем требованиям.
Список литературы
Александер C.R.M. Карманный справочник / Александер, Тернер - М.: Гиппо, 2004. - 136 с.
Анализ финансового состояния предприятия / Энциклопедия Экономиста, [Электронный ресурс] - URL:http://www.grandars.ru/college/ekonomika-firmy/finansovyy-analiz-predpriyatiya.html
Анализ финансово-хозяйственной деятельности предприятия / Энциклопедия Экономиста, [Электронный ресурс] - URL:http://www.grandars.ru/college/ekonomika-firmy/hozyaystvennaya-deyatelnost-predpriyatiy.html
Андерсон К. Менеджмент, ориентированный на потребителя: CRM-технологии как основа новых отношений с клиентом / К. Андерсон, К. Керр - М.: Гранд-Фаир, 2003. - 288 с.
Балдин. Информационные системы в экономике. Учебник / Балдин, Уткин - М.: Дашков и К, 2009. - 395 с.
Бланшар К. Как добиться лояльности клиентов в сфере услуг / К. Бланшар, Дж. Баллард - М.: Эксмо, 2008. - 208 с.
Боровков П. Финансово-экономический анализ / П.Боровков - Корпоративный менеджмент [Электронный ресурс], 2008. - URL:http://www.cfin.ru/finanalysis/reports/fin-ec_analysis.shtml
Бухгалтерская отчетность ЗАО «Сибтехнология» за 2008 - 2011 гг.
Вертоградов В. Как оценить эффективность внедрения CRM-систем. Другой взгляд / Владимир Вертоградов // Коммерческий директор - 2006, №2 [Электронный ресурс]
Листинг
//
// ContactViewController.swift
// SmartyCRM
//
// Created by Иван on 09.12.15.
// Copyright © 2015 Kirill. All rights reserved.
//
import UIKit
import SnapKit
import SwiftyJSON
import Kingfisher
import MessageUI
import PromiseKit
class ContactViewController: UIViewController,UITableViewDelegate, UITableViewDataSource,UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate,MFMailComposeViewControllerDelegate {
var relatedElemetsCount : [Int] = []
var tableView = UITableView()
var isOverLimit : Bool?
var noteCellPosition : Int?
var photoCellPosition : Int?
var commentsCellPosition : Int?
var deleteButtonPosition : Int?
let typeContactCell = UniversalCell()
let groupCell = UniversalCell()
let countryCell = UniversalCell()
let noteCell = SettingsEditStageCell()
let relatedCells : [RelatedCell] = [RelatedCell(),RelatedCell(),RelatedCell()]
var editMode = false
var relatedContacts:[CDContact] = []
var relatedNotes:[CDNote] = []
var relatedTasks:[CDTask] = []
var isAdditionalInformationShown = false
var editContact = UIBarButtonItem()
var saveContact = UIBarButtonItem()
var universalIndexs: [Int]?
var dateOfBirthdayIndexPath: NSIndexPath?
var contactMode = false
var profileCells :[UITableViewCell] = []
var contact: CDContact? {
didSet {
let relatedContactsIds : [String] = (contact!.relatedContacts as? [String] ?? [])
var relatedNotesIds : [String] = []
var relatedTasksIds : [String] = []
relatedContacts = []
relatedNotes = []
relatedTasks = []
let notes = UIDataProvider.instance.getCollection(CDNote.self)
for note in notes{
if let relatedCont = note.relatedContacts{
for relatedContact in (relatedCont as? [String])!{
if relatedContact == contact!.id{
relatedNotesIds.append(note.id!)
}
}
}
}
let tasks = UIDataProvider.instance.getCollection(CDTask.self)
for task in tasks{
if let relatedCont = task.relatedContacts{
for relatedContact in (relatedCont as? [String])!{
if relatedContact == contact!.id{
relatedTasksIds.append(task.id!)
}
}
}
}
for id in relatedContactsIds{
self.relatedContacts.append(CoreDataManager.instance.getObject(CDContact.self, id: id)!)
}
for id in relatedNotesIds{
self.relatedNotes.append(CoreDataManager.instance.getObject(CDNote.self, id: id)!)
}
for id in relatedTasksIds{
self.relatedTasks.append(CoreDataManager.instance.getObject(CDTask.self, id: id)!)
}
relatedElemetsCount = [self.relatedContacts.count,self.relatedNotes.count,self.relatedTasks.count]
}
}
var textViewHeight = CGFloat(-100)
var textViewComments = CGFloat(-100)
var group: CDGroup?
init() {
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
view = UIView()
editContact = UIBarButtonItem(title: "butTaskChange".localized, style: .Plain, target: self, action: #selector(tapEditContact))
saveContact = UIBarButtonItem(title: "doneButton" .localized, style: .Plain, target: self, action: #selector(saveChanges))
view.addSubview(tableView)
tableView.tableFooterView = UIView()
tableView.snp_makeConstraints{ make in
make.edges.equalTo(view)
}
setupTableView()
setupAdditionalInformation()
hide = additionalInformationCells.count == 1
commentsCellPosition = additionalInformation.count
tableView.dataSource = self
tableView.delegate = self
self.tableView.registerClass(HeaderCell .self, forCellReuseIdentifier: "headerCell")
self.tableView.registerClass(AdditionalCell.self, forCellReuseIdentifier: "additionalCell")
self.tableView.registerClass(ValueTypeCell .self, forCellReuseIdentifier: "vtCell")
self.tableView.registerClass(ButtonCell .self, forCellReuseIdentifier: "buttonCell")
}
var hide = true
func setupAdditionalCell(value:String, type:String, canAdd: Bool, index: Int) ->AdditionalCell{
let cell = AdditionalCell()
additionalInformation.insert((type: type, value: value), atIndex: index)
cell.valueField.text = value
cell.valueField.placeholder = Constants.phoneTypes.contains(type) ? AdditionalType.Phone.description : type
cell.valueField.enabled = !canAdd
cell.valueField.keyboardType = Constants.phoneTypes.contains(type) ? .PhonePad : .Default
cell.typeField .enabled = Constants.phoneTypes.contains(type)
cell.typeField.setTitle(type , forState: .Normal)
cell.deleteCell.hidden = canAdd
cell.addButton .hidden = !canAdd
cell.addCell .hidden = !canAdd
cell.buttonTappedHandler = { [weak self] text in
guard let _self = self else { return }
let indexPath = _self.tableView.indexPathForCell(cell)!
_self.additionalInformation[indexPath.row - 1].value = text
_self.saveAdditionalInformation()
}
if Constants.phoneTypes.contains(type){
cell.changeTypeHandler = { [weak self] in
let universalController = UniversalController(title:"phoneType".localized,variants:Constants.phoneTypes)
self?.navigationController?.pushViewController(universalController , animated: true)
universalController.buttonTappedHandler = { [weak self] index in
if let indexPath = self?.tableView.indexPathForCell(cell) {
if let cell = self?.tableView.cellForRowAtIndexPath(indexPath) as? AdditionalCell{
cell.typeField.setTitle(Constants.phoneTypes[index], forState: .Normal)
}
self?.additionalInformation[indexPath.row - 1].type = Constants.phoneTypes[index]
self?.saveAdditionalInformation()
}
}
}
}
if canAdd{
cell.additingCellTappedHandler = {
self.commentsCellPosition = (self.commentsCellPosition ?? 0) + 1
let indexPath = self.tableView.indexPathForCell(cell)!
let typeField = self.additionalInformation[indexPath.row - 1].type == "clientPhones".localized ? Constants.phoneTypes[0] : self.additionalInformation[indexPath.row - 1].type
self.additionalInformationCells.insert(self.setupAdditionalCell("", type:typeField, canAdd: false,index: indexPath.row - 1) , atIndex: indexPath.row)
if let dateOfBirthdayIndexPath = self.dateOfBirthdayIndexPath {
self.dateOfBirthdayIndexPath = NSIndexPath(forRow: dateOfBirthdayIndexPath.row + 1, inSection: dateOfBirthdayIndexPath.section)
}
self.saveAdditionalInformation()
self.tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
}}else{
cell.deletingTappedHandler = {
self.commentsCellPosition = (self.commentsCellPosition ?? 0) - 1
let indexPath = self.tableView.indexPathForCell(cell)!
if let dateOfBirthdayIndexPath = self.dateOfBirthdayIndexPath {
self.dateOfBirthdayIndexPath = NSIndexPath(forRow: dateOfBirthdayIndexPath.row - 1, inSection: dateOfBirthdayIndexPath.section)
}self.additionalInformation.removeAtIndex(indexPath.row - 1)
self.additionalInformationCells.removeAtIndex(indexPath.row )
self.saveAdditionalInformation()
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
}
}
return cell
}
func setupBithdayCell(value:String, type:String) ->AdditionalBirthdayCell{
let cell = AdditionalBirthdayCell()
additionalInformation.append((type: type, value: value))
cell.birthdayField.text = value
cell.typeField .text = type
cell.getPickerView = { [weak self] in
if let indexPath = self?.tableView.indexPathForCell(cell){
self?.dateOfBirthdayIndexPath = indexPath
}
self?.editDeadline()
}
return cell}
func setupCommentCell(value:String, type:String) ->AdditionalCommentCell{
let cell = AdditionalCommentCell()
additionalInformation.append((type: type, value: value))
cell.textView.text = value
cell.beginEditingTextViewHandler = { [weak self] in
if let indexPath = self?.tableView.indexPathForCell(cell){
self?.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: true)
}
}
cell.descriptionChanged = { [weak self]text in
if let indexPath = self?.tableView.indexPathForCell(cell){
cell.textView.becomeFirstResponder()
self?.contact?.additionalComment = text
self?.additionalInformation[indexPath.row - 1].value = text
self?.saveAdditionalInformation()
elf?.textViewComments = cell.textView.contentSize.height + CGFloat(Constants.additionalHeightForMultiLineFields)
self?.tableView.beginUpdates()
self?.scrollToCursorForTextView(cell.textView)
self?.tableView.endUpdates()
}
}
return cell
}
func setupAdditionalCell(value:String, type:String) ->ValueTypeCell{
let cell = ValueTypeCell()
additionalInformation.append((type: type, value: value))
let isComments = type == AdditionalType.Comments.description ? true : false
cell.valueField.text = value
cell.valueField.hidden = isComments
cell.typeField .text = type
cell.typeField.hidden = isComments
cell.textView.text = value
cell.textView.hidden = !isComments
cell.textView.userInteractionEnabled = false
return cell
}
var additionalInformation : [(type: String, value:String)] = []
func getAdditionalDataFromType(type: AdditionalType)-> [UITableViewCell]{
ar cellArray : [UITableViewCell] = []
if let contact = self.contact{
var cell = UITableViewCell()
switch type {
case AdditionalType.Phone:
if let phones = contact.additionalPhones as? [AnyObject] where phones.count != 0 {
for phone in phones{
let json = JSON(phone)
guard let phoneTypeInt = json["type" ].int else { continue }
guard let phoneNumber = json["number"].string else { continue }
cell = editMode ?
setupAdditionalCell(phoneNumber,type: convertPhoneType(phoneTypeInt), canAdd: false,index: additionalInformation.count) :
setupAdditionalCell(phoneNumber,type: convertPhoneType(phoneTypeInt))
cellArray.append(cell)
}
}
if editMode {
cell = setupAdditionalCell(type.description,type: type.description, canAdd: true,index: additionalInformation.count)
cellArray.append(cell)
}
break
case AdditionalType.Company:
if (contact.additionalCompanies as? [String])?.count != 0 {
if let companies = contact.additionalCompanies as? [String]{
for company in companies {
let cell = editMode ?
setupAdditionalCell(company,type: type.description, canAdd: false,index: additionalInformation.count) :
setupAdditionalCell(company,type: type.description)
cellArray.append(cell)
}
}
}
if editMode {
cell = setupAdditionalCell(type.description,type: type.description, canAdd: true,index: additionalInformation.count)
cellArray.append(cell)
}
break
case AdditionalType.Names:
if (contact.additionalContactNames as? [String])?.count != 0 {
if let contactNames = contact.additionalContactNames as? [String]{
for contactName in contactNames {
let cell = editMode ?
setupAdditionalCell(contactName,type: type.description, canAdd: false,index: additionalInformation.count) :
setupAdditionalCell(contactName,type: type.description)
cellArray.append(cell)
}
}
}
if editMde {
cell = setupAdditionalCell(type.description,type: type.description, canAdd: true,index: additionalInformation.count)
cellArray.append(cell)
}
break
case AdditionalType.Position:
if (contact.additionalPositions as? [String])?.count != 0 {
if let positions = contact.additionalPositions as? [String]{
for position in positions {
let cell = editMode ?
setupAdditionalCell(position,type: type.description, canAdd: false,index: additionalInformation.count) :
setupAdditionalCell(position,type: type.description)
cellArray.append(cell)
}
}
}
if editMode {
cell = setupAdditionalCell(type.description,type: type.description, canAdd: true,index: additionalInformation.count)
cellArray.append(cell)
}
reak
case AdditionalType.Messengers:
if (contact.additionalMessengers as? [String])?.count != 0 {
if let messengers = contact.additionalMessengers as? [String]{
for messenger in messengers{
let cell = editMode ?
setupAdditionalCell(messenger,type: type.description, canAdd: false,index: additionalInformation.count) :
setupAdditionalCell(messenger,type: type.description)
cellArray.append(cell)
}
}
}
if editMode {
cell = setupAdditionalCell(type.description,type: type.description, canAdd: true,index: additionalInformation.count)
cellArray.append(cell)
}
break
case AdditionalType.Mail:
if (contact.additionalAddresses as? [String])?.count != 0 {
if let addresses = (contact.additionalAddresses as? [String]){
for address in addresses{
let cell = editMode ?
setupAdditionalCell(address,type: type.description, canAdd: false,index: additionalInformation.count) :
setupAdditionalCell(address,type: type.description)
cellArray.append(cell)
}
}
}
if editMode {
cell = setupAdditionalCell(type.description,type: type.description, canAdd: true,index: additionalInformation.count)
cellArray.append(cell)
}
break
case AdditionalType.SocialNetwork:
if (contact.additionalSocialNetworks as? [String])?.count != 0 {
if let socialNetworks = (contact.additionalSocialNetworks as? [String]){
for socialNetwork in socialNetworks{
let cell = editMode ?
setupAdditionalCell(socialNetwork,type: type.description, canAdd: false,index: additionalInformation.count) :
setupAdditionalCell(socialNetwork,type: type.description)
cellArray.append(cell)
}
}
}
if editMode {
cell = setupAdditionalCell(type.description,type: type.description, canAdd: true,index: additionalInformation.count)
cellArray.append(cell)
}
break
case AdditionalType.WebSite:
if (contact.additionalWebSites as? [String])?.count != 0 {
if let webSites = (contact.additionalWebSites as? [String]){
for webSite in webSites{
let cell = editMode ?
setupAdditionalCell(webSite,type: type.description, canAdd: false,index: additionalInformation.count) :
setupAdditionalCell(webSite,type: type.description)
cellArray.append(cell)
}
}
}
if editMode {
cell = setupAdditionalCell(type.description,type: type.description, canAdd: true,index: additionalInformation.count)
cellArray.append(cell)
}
break
case AdditionalType.Bithday:
if (contact.additionalBirthday != 0){
let formatter = NSDateFormatter()
foratter.dateStyle = .ShortStyle
let bithday = formatter.stringFromDate(NSDate(timeIntervalSince1970: contact.additionalBirthday))
et cell = editMode ?
setupBithdayCell(bithday,type: type.description) :
setupAdditionalCell(bithday,type: type.description)
cellArray.append(cell)
}else{
if editMode {
cell = setupBithdayCell("",type: type.description)
cellArray.append(cell)
}
}
break
case AdditionalType.Comments:
if let comments = contact.additionalComment where !comments.isEmpty{
let cell = editMode ?
setupCommentCell(comments,type: type.description) :
setupAdditionalCell(comments,type: type.description)
cellArray.append(cell)
} else{
if editMode {
cell = setupCommentCell("",type: type.description)
cellArray.append(cell)
}
}
break
default:
return []
}
}
return cellArray
}
var additionalInformationCells : [UITableViewCell] = []
func setupAdditionalInformation() {
additionalInformationCells.removeAll()
additionalInformation.removeAll()
let typesAdditionalInf = contactMode ? Constants.typesAdditionalInformationOrganization : Constants.typesAdditionalInformationPeople
additionalInformationCells.append(HeaderCell())
for typeAdditionalInf in typesAdditionalInf{
let getCells = getAdditionalDataFromType(typeAdditionalInf)
additionalInformationCells += getCells
}
}
override func viewDidLoad() {
super.viewDidLoad()
if #available(iOS 9.0, *) {
tableView.cellLayoutMarginsFollowReadableWidth = false
}
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
deleteButtonPosition = hide ? 1 : 2
return hide ? 2 : 3
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (section == 0){
return profileCells.count
}else if section == 1{
if hide{
if let contact = self.contact{
return !(contact.isOverLimit ?? false) ? 1 : 0
}
return 0
}else{
return isAdditionalInformationShown ? additionalInformationCells.count : 1
}
}else{
return Int(!editMode)
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.section == 0{
return profileCells[indexPath.row]
}else if indexPath.section == 1 && !hide{
return additionalInformationCells[indexPath.row]
}else{
let cell = tableView.dequeueReusableCellWithIdentifier("buttonCell", forIndexPath: indexPath) as! ButtonCell
return cell
}
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.section == 0{
if indexPath.row == 0{
return 45
}
if indexPath.row == photoCellPosition{
return 98
}
if indexPath.row == noteCellPosition {
if textViewHeight > 48{
return maxHeightTextView > textViewHeight ? textViewHeight : maxHeightTextView
}
}
}else{
if indexPath.row == commentsCellPosition && editMode{
if textViewComments > 48{
return maxHeightTextView > textViewComments ? textViewComments : maxHeightTextView
}
}
}
return 48
}
func tableView(tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool {
if indexPath.section == 0{
let cell = tableView.cellForRowAtIndexPath(indexPath)
if cell is RelatedCell{
return true
}
if editMode{
for index in universalIndexs!{
if indexPath.row == index{
return true
}
}
}
return false
}
return true
}
var deltaRelatedNotes :[CDNote] = []
var deltaRelatedTasks :[CDTask] = []
var deltaRelatedContacts : [CDContact] = []
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
let groups = UIDataProvider.instance.getCollection(CDGroup.self,predicate: NSPredicate(format: "section == 'contacts'"))
if indexPath.section == deleteButtonPosition{
self.contact?.isArchive = true
self.navigationController?.popViewControllerAnimated(true)
}else if indexPath.section == 1{
let cell = tableView.cellForRowAtIndexPath(indexPath)
if (cell is HeaderCell){
isAdditionalInformationShown = !isAdditionalInformationShown
setupAdditionalInformation()
self.tableView.reloadSections(NSIndexSet(index: indexPath.section), withRowAnimation: .Fade)
if isAdditionalInformationShown{
self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
}
}else if (cell is AdditionalCell){
if let cell = cell as? AdditionalCell{
if let indexPath = self.tableView.indexPathForCell(cell){
self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: true)
}
}
}
}else {
let cell = tableView.cellForRowAtIndexPath(indexPath)
if (cell is RelatedCell){
if let cell = cell as? RelatedCell{
if cell.titleLabel.text! == "clientCardTitle".localized{
let relatedViewController = RelatedContactsViewController(rContacts: self.relatedContacts)
relatedViewController.contact = self.contact
relatedViewController.relatedContactsSaved = { [weak self] (relatedContacts:[CDContact]) in
//cell.badge.text = relatedContacts.count > 0 ? String(relatedContacts.count) : "+"
self!.deltaRelatedContacts = []
for contact in (self?.relatedContacts)!{
if relatedContacts.contains(contact){
}else{
self?.deltaRelatedContacts.append(contact)
}
}
self?.relatedContacts = relatedContacts
}
relatedViewController.editMode = editMode
self.navigationController?.pushViewController(relatedViewController, animated: true)
}else if cell.titleLabel.text! == "tasksPreReminderDesc".localized{
let relatedViewController = RelatedNotesViewController(rNotes: self.relatedNotes)
relatedViewController.relatedNotesSaved = { [weak self] (relatedNotes:[CDNote]) in
cell.badge.text = relatedNotes.count > 0 ? String(relatedNotes.count) : "+"
self!.deltaRelatedNotes = []
for note in (self?.relatedNotes)!{
if relatedNotes.contains(note){
}else{
self?.deltaRelatedNotes.append(note)
}
}
self?.relatedNotes = relatedNotes
}
relatedViewController.editMode = editMode
self.navigationController?.pushViewController(relatedViewController, animated: true)
}else{
let relatedViewController = RelatedTasksViewController(rTasks: self.relatedTasks)
relatedViewController.relatedTasksSaved = { [weak self] (relatedTasks:[CDTask]) in
cell.badge.text = relatedTasks.count > 0 ? String(relatedTasks.count) : "+"
self!.deltaRelatedTasks = []
for task in (self?.relatedTasks)!{
if relatedTasks.contains(task){
}else{
self?.deltaRelatedTasks.append(task)
}
}
self?.relatedTasks = relatedTasks
}
relatedViewController.editMode = editMode
self.navigationController?.pushViewController(relatedViewController, animated: true)
}
}
}else if (cell is UniversalCell){
if let cell = cell as? UniversalCell{
self.findViewController(ContactRootViewController)?.tabBarShown = false
if (cell.name.text == "clientCardPersonalDataCountry".localized) {
var countriesText : [String] = []
var countriesValues: [String] = []
let userCountry = UIDataProvider.instance.getUserProfile()?.country
for tkCountry in Constants.tkCountries {
if (tkCountry != userCountry) {
countriesValues.append(tkCountry)
}
}
countriesValues.sortInPlace { $0.localized < $1.localized }
if (userCountry != nil) {
countriesValues.insert(userCountry!, atIndex: 0)
}
for countryValue in countriesValues {
countriesText.append(countryValue.localized)
}
let universalController = UniversalController(title:"clientCardPersonalDataCountry".localized ,variants:countriesText)
navigationController?.pushViewController(universalController , animated: true)
universalController.buttonTappedHandler = { [weak self]index in
cell.status.text = countriesText[index]
self?.contact?.country = countriesValues[index]
}
}else if (cell.name.text == "leftBarMenuGroupTitle".localized) {
var titlesGroup : [String] = []
for group in groups{
titlesGroup.append(group.title!)
}
let universalController = UniversalController(title:"common_groups".localized ,variants:titlesGroup)
navigationController?.pushViewController(universalController , animated: true)
universalController.buttonTappedHandler = { [weak self]index in
self?.groupCell.status.text = groups[index].title
self?.contact?.group = groups[index]
if let contact = self?.contact{
UIDataProvider.instance.saveCollectionObject(contact)
}
}
}else if (cell.name.text == "clientCardTypeContact".localized) {
let titlesGroup : [String] = ["clientCardTypeNormal".localized,"clientCardTypeKey".localized]
let universalController = UniversalController(title:"clientCardTypeContact".localized ,variants:titlesGroup)
navigationController?.pushViewController(universalController , animated: true)
universalController.buttonTappedHandler = { [weak self] index in
self?.typeContactCell.status.text = titlesGroup[index]
self?.contact?.isImportant = Bool(index)
}
}
}
}else if (cell is TextFieldCell){
if let cell = cell as? TextFieldCell{
if let indexPath = self.tableView.indexPathForCell(cell){
self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: true)
}
}
}else if (cell is SettingsEditStageCell){
if let cell = cell as? SettingsEditStageCell{
if let indexPath = self.tableView.indexPathForCell(cell){
self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: true)
}
}
}
}
}
func saveAdditionalInformation() {
var phones = self.contact?.additionalPhones as? [AnyObject] ?? []
var companies = self.contact?.additionalCompanies as? [String] ?? []
var contactNames = self.contact?.additionalContactNames as? [String] ?? []
var positions = self.contact?.additionalPositions as? [String] ?? []
var skype = self.contact?.additionalMessengers as? [String] ?? []
var address = self.contact?.additionalAddresses as? [String] ?? []
var socialNet = self.contact?.additionalSocialNetworks as? [String] ?? []
var webSites = self.contact?.additionalWebSites as? [String] ?? []
let chats = self.contact?.chats as? [AnyObject] ?? []
phones.removeAll()
if contactMode{
contactNames.removeAll()
}else{
companies.removeAll()
}
positions.removeAll()
skype.removeAll()
address.removeAll()
socialNet.removeAll()
webSites.removeAll()
for item in self.additionalInformation{
if item.type != item.value && !item.value.isEmpty{
switch item.type {
case Constants.phoneTypes[0]:
var dict = ["number":"","type": 0]
dict["number"] = item.value
phones.append(dict)
break
case Constants.phoneTypes[1]:
var dict = ["number":"","type": 1]
dict["number"] = item.value
phones.append(dict)
break
case Constants.phoneTypes[2]:
var dict = ["number":"","type": 2]
dict["number"] = item.value
phones.append(dict)
break
case Constants.phoneTypes[3]:
var dict = ["number":"","type": 3]
dict["number"] = item.value
phones.append(dict)
break
case "contactNames".localized:
contactNames.append(item.1)
break
case "managerPosition".localized:
positions.append(item.value)
break
case "clientCompany".localized:
companies.append(item.value)
break
case "clientMessengers".localized:
skype.append(item.value)
break
case "clientCardPersonalDataMail".localized:
address.append(item.value)
break
case "clientSocialNetwork".localized:
socialNet.append(item.value)
break
case "clientWebSite".localized:
webSites.append(item.value)
break
case "clientDateOfBirtDay".localized:
break
case "comments".localized:
break
default:
phones.append(item.1)
break
}
}
}
self.contact?.additionalPhones = phones
self.contact?.additionalCompanies = companies
self.contact?.additionalContactNames = contactNames
self.contact?.additionalPositions = positions
self.contact?.additionalMessengers = skype
self.contact?.additionalAddresses = address
self.contact?.additionalSocialNetworks = socialNet
self.contact?.add...
Подобные документы
Создание, изучение и разработка приложение на Android. Среда разработки приложения DelphiXE5. Установка и настройка среды программирования. Этапы разработки приложения. Инструменты для упрощения конструирования графического интерфейса пользователя.
курсовая работа [1,6 M], добавлен 19.04.2017Обзор подходов к разработке музейных приложений с элементами дополненной реальности, формирование требований к ним. Выбор методов разработки приложения, разработка пользовательского интерфейса. Принципы тестирования. Реализация раздела "Распознавание".
дипломная работа [2,8 M], добавлен 03.07.2017Общая характеристика и структурная схема приложения, требования к нему и функциональные особенности, сферы практического применения. Обоснование выбора языка программирования. Описание интерфейса и инструкция пользователя. Проведение листинга программы.
дипломная работа [1,0 M], добавлен 10.07.2017Разработка адресных и технических требований к игре. Написание сценария. Общая концепция разработки приложения. Разработка схем алгоритмов приложения. Игровые технологии. Выбор среды и программированного языка. Описание пользовательского интерфейса.
курсовая работа [1,6 M], добавлен 14.06.2014Разработка программного продукта для экспорта спецификации из приложения PartList. Выбор метода передачи информации в файл, формата для представления. Разработка конвертера, реализация пользовательского интерфейса. Обоснование актуальности разработки.
дипломная работа [2,6 M], добавлен 25.09.2014Современное состояние рынка мобильных приложений. Основные подходы к разработке мобильных приложений. Обоснование выбора целевой группы потребителей приложения. Этапы проектирования и разработки мобильного приложения для операционной системы Android.
курсовая работа [987,1 K], добавлен 27.06.2019Разработка программного решения по созданию мобильного приложения. Изучение технологий для разработки приложений. Анализ работы торговых агентов. Обоснование выбора языка программирования. Проектирование интерфейса структуры и верстка, листинг программы.
дипломная работа [2,2 M], добавлен 08.06.2017Обзор мобильной ОС Android. Выбор инструментов и технологий. Проектирование прототипа графического интерфейса. Характеристика и описание пользовательского интерфейса. Проектирование и разработка базы данных. Определение списка необходимых разрешений.
курсовая работа [376,6 K], добавлен 13.09.2017Проектирование вариантов использования приложения. Анализ существующей версии приложения. Обоснование выбора инструментальных программных средств. Проектирование интерфейса пользователя. Адаптация под мобильные устройства. Описание программного продукта.
курсовая работа [2,8 M], добавлен 25.06.2017Проектирование структуры программы, принцип ее работы, сферы практического использования и оценка возможностей. Выбор и обоснование среды программирования. Разработка пользовательского интерфейса и модулей приложения. Проведение тестирования программы.
курсовая работа [637,7 K], добавлен 14.01.2015Создание автоматизированного рабочего места заместителя заведующего складом. Проектирование базы данных. Разработка программно-информационного ядра системы. Методика разработки клиентского приложения. Разработка организационного компонента системы.
курсовая работа [1,1 M], добавлен 05.06.2015Обоснование выбора программно-технических средств. Надежность программы и состав технических средств. Разработка структурной схемы программы, алгоритмического и программного интерфейса. Технология разработки интерфейса пользователя и программных модулей.
дипломная работа [3,2 M], добавлен 22.01.2013Разработка приложения для проверки использования времен глаголов в английском языке. Создание базы данных. Анализ используемых средств для реализации автоматического разбора текста. Проектирование мобильного приложения с помощью диаграмм деятельности.
дипломная работа [2,6 M], добавлен 13.09.2017Разработка и реализация демонстрационного многопоточного приложения. Выбор основных средств реализации. Описание логики работы приложения и разработка программного обеспечения. Описание пользовательского интерфейса. Реализация потоков в Delphi.
курсовая работа [462,5 K], добавлен 10.08.2014Исследование спецификации логической игры "Сапёр". Системное и функциональное проектирование приложения. Разработка программных модулей. Обзор классов, необходимых для создания интерфейса данного приложения. Инструменты для реализации логической игры.
курсовая работа [1,2 M], добавлен 13.01.2016Разработка программного продукта - приложения, позволяющего заносить данные анкетирования в базу данных MS SQL. Описание логики работы приложения, особенности пользовательского интерфейса. Формы просмотра анкет, описание процедур и функций программы.
курсовая работа [1,2 M], добавлен 16.08.2012Основные инструменты построения Web-приложения. Язык сценариев PHP. Системный анализ предметной области базы данных. Коды SQL запросов на создание таблиц. Разработка Web-приложения. Описание функциональности модулей. Система управления содержимым статей.
курсовая работа [4,8 M], добавлен 28.04.2014Проектирование удобного приложения для комфортной навигации по файлам облачного хранилища в одном файловом менеджере. Выбор интегрированной среды разработки. Выбор инструментов для визуализации приложения. Выбор средств отслеживания HTTPзапросов.
курсовая работа [3,6 M], добавлен 16.07.2016Анализ целевой аудитории. Функциональные характеристики пользовательского приложения. Разработка алгоритмов и интерфейса программного продукта, функций рабочей области. Написание скриптов на языке C#. Тестирование программы методом чёрного ящика.
дипломная работа [1,5 M], добавлен 09.11.2016Требования к аппаратным и операционным ресурсам. Логическая и физическая организация. Состав основных классов проекта. Технико-экономическое обоснование разработки программного средства. Задержки при обработке данных. Разработка интерфейса приложения.
дипломная работа [4,4 M], добавлен 16.06.2017