move-to-go

What is move-to-go?

move-to-go is a ruby-based migration tool for Lime Go.
It can take virtually any data source as input and generate a zip file that LIME Go likes.
These files can then easily be migrated to Lime Go by Lundalogik.
During an migration an automatic matching against all base data will be performed.

Organizations, Persons, Deals, Histories, Coworkers and Documents can be migrated to Lime Go.

Working with sources

To help you get started a couple of different sources are included in move-to-go.
These sources contains basic code and a folder structure for a specific migration.

You can list the available sources with

move-to-go list-sources

Current sources

Migrate from CSV-files

Migrate from Lime Easy

Migrate from a Excel-file

Migrate from VISMA Administration 2000

Migrate from Salesforce

Migrate from a custom source

To create a new project with

move-to-go new excel-migration excel

This will create a folder named excel-migration from the source excel. It is good practice to name the project after the customer that you are doing the migration for.

In the project folder you have a file called converter.rb. It is now your job to customize this script to do the data-mapping and adding tags. Follow the instructions in converter.rb to do the data-mapping.

To create the zip-file that should be sent to Lime Go use

move-to-go run

This will create a go_0.zip file. If the file already exists it will be replaced.

If the migration contains lots of data, the result will be split into several zip files.

What happens when you move to Lime Go?

Since Lime Go contains all organizations and persons an migration not an import in the traditional sense.
What you really do when migrating organizations is to tell Lime Go that these organizations are my customers.

When organizations (and persons) are migrated Lime Go will try to match your organizations with organizations in our database. Lime Go will try to match organizations by organization number, name, address, etc. If the migration contains more data about each organization then the probability that Lime Go will find a match increase.

If an organization is found it will get the relation set in the migration (default is Customer), responsible coworker, integration id, tags and custom fields. If a match is found Lime Go will not migrate fields such as address, phone number, website, etc since we believe that our data is more up to date than your data. Your data is only used for matching in this case.

If a match is not found, Lime Go will create a new organization with all data from the migrat file. The organization will be tagged with "FailedToMatch". This means that for these organizations address, phone number, etc will be migrated.

If more than one organization in the migration file refers to the same organization Lime Go the migrated organizations will be tagged with "PossibleDuplicate". Fields such as address, phone number, etc will not be migrated.

All migrated organizations will be tagged "Import".

Coworkers, deals and histories are always migrated as is. These objects are linked to an organization.

Integration id

It is required to set integration id for all migrated objects. The integration id for example used to connect deals to organizations and coworkers are deals. When migrating Lime Go will try to match migrated objects to existing objects by integration id.

If an integration id is missing in your migration file you can generate one from the row.

organization.integration_id=row.to_hash

As long as your data is free from duplicates this will create a unique key, which is also recallable with the exact same input data.

Rootmodel

The rootmodel is an object that keeps track of your migrated data and turns it into a format Lime Go can read. The rootmodel helps you keep track go objects and relations between them during the migration

Datasource -> [your code] -> rootmodel -> go.zip

Helpfull rootmodel code:

# create a brand new rootmodel. Usually only done once for an migrationrootmodel=MoveToGo::RootModel.new# Settings. The rootmodel is capable of storing how a brand new# Lime Go app should be set up. Most commonly; which custom fields should exist# and how the business statuses should be configuredrootmodel.settings.with_persondo|person|person.set_custom_field({:integration_id=>'shoe_size',:title=>'Shoe size',:type=>:String})endrootmodel.settings.with_dealdo|deal|deal.add_status({:label=>'1. Kvalificering'})deal.add_status({:label=>'2. Deal closed',:assessment=>MoveToGo::DealState::PositiveEndState})deal.add_status({:label=>'4. Deal lost',:assessment=>MoveToGo::DealState::NegativeEndState})end# Once a object, such as an organisation is created and mapped to migrated data# it should be added to the rootmodelorganisation=MoveToGo::Organisation.new()# Add data to your new fancy organisation…rootmodel.add_organization(organisation)# As migrated persons belong to an migrated organisation, they must be mapped# together. The rootmodel will help you with this:person=MoveToGo::Person.new()#Add data to your fancy new person…id=data_row['id']organisation=rootmodel.find_organization_by_integration_id(id)organisation.add_employee(person)# The same goes for deals and histories, however, the syntax differs slightly.# A deal or a history has relations to both organisations and personsdeal=MoveToGo::Deal.new()#Add data to your fancy new deal…org_id=deal_data_row['organisation_id']person_id=deal_ata_row['person_id']deal.customer=rootmodel.find_organization_by_integration_id(org_id)deal.customer_contact=rootmodel.find_person_by_integration_id(org_id)# History logs# There are five types of history logs:# - SalesCall: We talked to the client about a sale. This might be a phone call or a talk in person.# - Comment: This is a general comment about the organization or deal.# - TalkedTo: This is a general comment regarding a talk we had with someone at the client.# - TriedToReach: We tried to reach someone but failed.# - ClientVisit: We had a meeting at the client's site.comment=MoveToGo::Comment.new()comment.integration_id=...comment.text=...comment.created_by=rootmodel.find_coworker_by_integration_id(...)comment.deal=rootmodel.find_deal_by_integration_id(...)# If related to dealcomment.person=rootmodel.find_person_by_integration_id(...)# if related to personcomment.organization=rootmodel.find_organization_by_integration_id(...)# if related to organizationrootmodel.add_comment(comment)salesCall=MoveToGo::SalesCall.new()# Set properties...rootmodel.add_sales_call(salesCall)talkedTo=MoveToGo::TalkedTo.new()# Set properties...rootmodel.add_talked_to(talkedTo)triedToReach=MoveToGo::TriedToReach.new()# Set properties...rootmodel.add_tried_to_reach(triedToReach)clientVisit=MoveToGo::clientVisit.new()# Set properties...rootmodel.add_client_visit(clientVisit)Note:Whenhistorylogshavebeenmigratedtogo.It's possible to make a re-migrate to update fields, but it'snotpossibletochangetypeofhistorylog.

Organisations

A core concept in the Lime Go migration is a organisation. A organisation. When migrating an organisation to Lime Go, we will try to match the organisation to existing source data in Lime Go. The matching is performed by fuzzy lookups on all supplied data, meaning the more and better data you supply to the migration, the higher the likelihood of a positive match will be. Many of your supplied attributes will only be used for matching and won't override our source data in Lime Go, such as addresses. Attributes, such as organisation number or Bisnode-id, are considered more important then other attributes and will greatly improve the likelihood of a positive match.

An organisation has the following attributes and functions. Assuming we have read each organisation in the source data into a hash, row.

organisation=MoveToGo::Organisation.new()organisation.name=row['name']organization.organization_number=row['orgnr']organization.web_site=row['website']bisnode_id=row['Bisnode-id']# It's not uncommon that e-mail addresses are miss formed from a migration source.# MoveToGo supplies a helper function for thisifMoveToGo::EmailHelper.is_valid?(row['e-mail'])organization.email=row['e-mail']endorganization.with_postal_addressdo|address|address.street=row['street']address.zip_code=row['zip']address.city=row['city']endorganization.with_visit_addressdo|addr|addr.street=row['visit street']addr.zip_code=row['visit zip']addr.city=row['visit city']end# Add a responsible coworker to the organisationorganization.responsible_coworker=rootmodel.find_coworker_by_integration_id(row['Medarbetare'])# A very important and common thing is to set tags on organisationsorganization.set_tag(row['customer category'])# If you have created custom fields in the settings you can set their value.# First parameter is the id of the custom field and second is the desired valueorganization.set_custom_value(

Persons

Persons are employees of the organizations in Lime Go. Just as with the organisations, the migrated persons will be
matched against the source data in Lime Go.

person=MoveToGo::Person.new()person.first_name="Kalle"person.last_name="Kula"# It is common that the persons name in the migrated data isn't in seperate# fields, but as a single string. MoveToGo supplies a helper functionperson.parse_name_to_firstname_lastname_se(row['name'])# or# Validate email:ifMoveToGo::EmailHelper.is_valid?(row['Email'])person.email=row['Email']end# If the phone number data is a messperson.mobile_phone_number,person.direct_phone_number=MoveToGo::PhoneHelper.parse_numbers(row['Telefon'],[",","/","\\"])# or if it is very well formedperson.direct_phone_number=row['direct number']person.mobile_phone_number=row['mobile']person.position=row['position']# Add tags. Tags are used for valuesperson.set_tag("VIP")# If you have created custom fields during the setupperson.set_custom_value("shoe_size",row['shoe size'])

Smart helper functions and ruby trix

Parse a persons full name into a first and last name

person.parse_name_to_firstname_lastname_se(name,when_missing='')

Parse a phone number

number=MoveToGo::PhoneHelper.parse_numbers("046 - 270 48 00")# In the case there are multiple numbers in the same stringsource="046 - 270 48 00/ 031-712 44 00"number1,number2=MoveToGo::PhoneHelper.parse_numbers(source,'/')#If you are pick about only getting valid phone number you can use a strict mode.# Parses the specifed number_string and returns only valid numbers.MoveToGo::PhoneHelper.parse_numbers_strict(number_string,delimiters=',')MoveToGo::PhoneHelper.set_country_code(country_code)# Sets the country code used during parsning. The default is Swedish (:se) and# if you are parsing Swedish numbers you don't need to set the country code.