Class: Eco::API::UseCases::DefaultCases::TransferAccountCase

Inherits:
Common::Loaders::UseCase show all
Defined in:
lib/eco/api/usecases/backup/transfer_account_case.rb,
lib/eco/api/usecases/default_cases/transfer_account_case.rb

Instance Method Summary collapse

Methods inherited from Common::Loaders::UseCase

#initialize, type, #type

Methods inherited from Common::BaseLoader

<=>, created_at, #initialize, #name, name_only_once!, set_created_at!

Methods included from Common::ClassHelpers

#class_resolver, #descendants, #descendants?, #new_class, #resolve_class, #to_constant

Constructor Details

This class inherits a constructor from Eco::API::Common::Loaders::UseCase

Instance Method Details

#main(entries, people, session, options, usecase) ⇒ Void

Note:
  • the csv should contain a column destination-id containing the person id or external_id of the person that will be receiving the account.
  • when running this case, it is recommended to use the option -skip-batch-policies
  • it is highly recommended to either refresh the cache with -get-people or use the -get-partial option.

Usecase to actually transfer a user/account from one person to another person in the organization.

  • invocation command: -transfer-account-from

These are the steps and jobs it does:

  1. pair person entries (note: the destination-id entry could not be present, it will add it in such a case).
  2. retrieve from server persons that were not included in people.
  3. validation
    • a person should only receive account from just one user
    • a person should only give account to just one user
    • every account giver should have account
  4. create jobs
    • move giver's and receiver's accounts to dummy email addresses.
    • free up giver's and receiver's accounts.
    • switch email: set receiver's email to that of giver's dummy address.
      • to ensure account transfer, as we moved accounts to dummy emails, those dummy addresses should be used
    • invite receivers: adds account to the destination person in the dummy email.
      • actual user/account transfer to the person/receiver
      • no notification will be recived by the user, because of the dummy address at this stage
    • restore email: sets the receiver email from the dummy address to the final email.
      • the final email inbox will receive a notification of email change

Parameters:

Options Hash (options):

  • :include (Hash<Symbol, Object>)

    things that should be included.

    • :email (Boolean) [false] if the email should be transferred as well (command option: -include-email)
  • :skip (Hash<Symbol, Object>)

    things that should be excluded.

    • :api_policies (Boolean) [false] if the api policies should be skipped (command option: -skip-api-policies)

Returns:

  • (Void)


39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/eco/api/usecases/default_cases/transfer_account_case.rb', line 39

def main(entries, people, session, options, usecase)
  micro    = session.micro
  move     = session.new_job("main", "move email accounts", :update, usecase, :account)
  free     = session.new_job("main", "free up accounts",    :update, usecase, :account)
  switch   = session.new_job("main", "switch email",        :update, usecase, :core)
  invite   = session.new_job("post", "invite receivers",    :update, usecase, :account)
  restore  = session.new_job("post", "restore email",       :update, usecase, :core)

  with_each_person_pair(entries, people, session, options) do |src_person, dst_person|
    # capture actual initial information
    src_doc   = src_person..doc
    src_email = src_person.email
    src_dummy = dummy_email(src_person)
    dst_email = dst_person.email
    dst_dummy = dummy_email(dst_person)
    copy_src_email  = options.dig(:include, :email) || !dst_person.
    dst_end_email   = copy_src_email ? src_email : dst_email

    # account email renamings are necessary to avoid uncertainty and ensure no email taken error
    move.add(dst_person)    {|dst| dst.email = dst_dummy}
    move.add(src_person)    {|src| src.email = src_dummy}
    # free accounts up!
    free.add([dst_person, src_person]) {|person| person. = nil}
    # to effectivelly transfer the user/account, email should be the same during invite
    # otherwise the account doesn't actually get transferred but just copied
    switch.add(dst_person)  {|dst| dst.email = src_dummy}
    # do the actual transfer of account
    invite.add(dst_person)  {|dst| dst. = src_doc}
    # recover the original email, if the receiver had account
    restore.add(dst_person) {|dst| dst.email = dst_end_email}
  end.tap do |units|
    if options[:simulate]
      units.each {|unit| puts unit.persons.map(&:external_id).join(" --> ")}
    end
  end
end

#processObject



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/eco/api/usecases/backup/transfer_account_case.rb', line 7

def process
  @cases.define("transfer-account", type: :sync) do |entries, people, session, options, usecase|
     = session.job_group("main").new("remove account", usecase: usecase, type: :update, sets: :account)
        = session.job_group("post").new("add account", usecase: usecase, type: :update, sets: :account)

    strict_search = session.config.people.strict_search? && (!options[:search]&.key?(:strict) || options.dig(:search, :strict))

    done = []; pending = []
    pairs = entries.each_with_object([]) do |source|
      entry_hash = source.internal_entry
      unless entry_hash.key?("destination-id")
        session.logger.error("You haven't defined a column 'destination-id' to whom the account should be transferred")
        exit(1)
      end
      if peer_id = entry_hash["destination-id"]
        if peer = entries.entry(id: peer_id, external_id: peer_id)
          if done.include?(peer)
            session.logger.error("You paired '#{peer_id}' twice. A person can only receive account from 1 user")
            exit(1)
          end
          pending.delete(source)
          pending.delete(peer)
          done.push(source).push(pair)
          [source, peer]
        else
          pending.push(source)
          nil
        end
      else
        pending.push(source)
      end
    end.compact

    # Data input integrity check
    unless pending.empty?
      msg  = "You haven't defined a pair for the following ids:"
      msg += pending.each_with_object("") do |entry, str|
        str << "\n#{entry.id || entry.external_id}"
      end
      session.logger.error(msg)
      exit(1)
    end

    pairs.each do |pair|
      src_entry, dst_entry = pair
      unless src_person = people.find(src_entry, strict: strict_search)
        session.logger.error("This person does not exist: #{src_entry.to_s(:identify)}")
        exit(1)
      end

      unless dst_person = people.find(dst_entry,  strict: strict_search)
        session.logger.error("This person does not exist: #{dst_person.to_s(:identify)}")
        exit(1)
      end

      unless  = src_person.&.doc
        session.logger.error("You are trying to move account from a person that doesn't have: #{src_person.id | src_person.external_id}")
        exit(1)
      end

      if dst_person.email.to_s.strip.empty?
        session.logger.error("A person you are trying to add account doesn't have email: #{dst_person.id | dst_person.external_id}")
        exit(1)
      end

      src_person. = nil
      .add(src_person)
      .add(dst_person) do |person|
        # only if we got to remove the account of the original person
        if  && src_person.as_update == {}
          person. = 
        end
      end

    end

  end
end