Rupeal
RSSLinkedInTwitterFacebook

Arquivo para July, 2009

Autoridade vs Poder

Gostei do último post do Luís Martins Simões sobre um tema que já tinha sido abordado por mim num dos seus seminários de Liderança.

Autoridade, Poder, Poder Interior, Poder Exterior… conceitos que explicam a diferença entre inspirar por medo ou por respeito.

Não deixem de ler!

Rui Alves on July 25th, 2009

Uncategorized

0
 

Pagar online – Vencer o medo em pt

Ao oferecer um serviço exclusivamente online em Portugal (www.invoicexpress.com) enfrentamos uma série de barreiras associadas ao medo da mudança / adopção de novas tecnologias.

O maior desses medos é o de fornecer dados bancários para efectuar o pagamento. Mesmo com o MBNET e o PAYPAL ainda há muita gente que prefere os meios mais tradicionais.

A forma que encontrá-mos para contornar este problema foi oferecer um meio de pagamento exclusivo para Portugal, suportando os nossos bem conhecidos MultiBancos.
Após analisar algumas alternativas escolhemos como parceiro para este serviço a Hi-Media e o seu Serviço Compra Fácil.

Este serviço desponibiliza um webservice através do qual podemos pedir a geração de referências multibanco notificando-nos quando estas são pagas.

De uma perspectiva mais técnica como decorre o processo e como o integramos na nossa aplicação Rails?

  1. O utilizador, cliente do invoic€xpress escolhe o plano desejado, selecciona a opção de pagamento com multibanco e selecciona a opção gerar referência.
  2. O invoic€xpress gera um token único para a referência
    token = Digest::SHA1.hexdigest([Time.now, rand].join)
  3. Constroi o url para onde pretende ser notificado do pagamento, incluindo este token único
    url = "https://www.invoicexpress.net/references/payed/#{@mbreference.token}"
  4. Coloca esse URL e os restantes parametros necessários no pedido para o webservice compra fácil e efectua o pedido.
    factory = SOAP::WSDLDriverFactory.new("http://hm.comprafacil.pt/SIBSClick/webservice/clicksmsV4.asmx?WSDL")
    soap = factory.create_rpc_driver
    soapResponse = soap.SaveCompraToBDValor1(:origem=>url, :IDCliente=>"cliente_teste",
     :password=>"teste_password", :valor=> value , :informacao=>"teste", :IDUserBackoffice=>"-1")
  5. Guarda a referência multibanco gerada na BD
    @mbreference.reference = soapResponse.referencia
  6. O cliente desloca-se ao MB e efectua o pagamento
  7. O sistema compra-fácil notifica o invoic€xpress usando URL que indicámos no pedido (passo 3)
  8. O invoic€xpress recebe a notificação, e procura a referência através do token único, activando assim a subscrição paga pelo cliente.
    mbreference = Mbreference.find_by_token(params[:reference_token])
    mbreference.state = "payed"
    mbreference.save

Para os mais distraidos foram menos de 20 linhas de código…

O código é apresentada numa versão simplificada apenas para efeitos demonstrativos.

Não poderá ser descurado o facto de estarmos a trabalhar com dinheiro e com dados de clientes, é sempre necessário garantir o máximo de segurança possível usando HTTPS.

Apesar de ser uma solução especifica para Portugal, é de simples implementação e é uma forte ajuda para quebrar uma barreira à adopção deste tipo de aplicações web.

Rui Alves on July 14th, 2009

Software Development

1
 

RUPEAL’s website development process

We’ve recently launched our new website and thought it would be nice to reveal a little about the overall process and hopefully hear about yours.

There are many steps involved on the development of an website. From the original idea until the launch there is an entire cycle that we have to go trough.

Functional Analysis
We start off by talking about the goal of the website. In this step we need to understand the purpose of the website, clients, desired look & feel and the message to be expressed. For the Designer this step is crucial to understand the path to follow.

In the RUPEAL website we wanted this redesign to focus on the company services, with a clean and minimalist design and a direct approach.

Design
Depending on the size of the project, the design phase may vary a lot. In this case we started of with some wireframes to decide the overall position of the content and navigation. Then we did a Photoshop mockup, where we defined the look of the site, which allowed us to discuss and make changes before proceeding with development.

Development
We like to start with an PHP and CSS prototype. It allows us to have a functional website, that we can play around and quickly modify. This allows us to do cross browser testing and code validation while the amount of code is still bearable. With a functional prototype we can probe others for input much earlier in the process and they can get a better view of the final result.

With the prototype done, we move to CMS integration.

With the RUPEAL website we needed a CMS that was able to accommodate both static and dynamic content, easy to use and rapid to integrate. We chose WordPress.

Although WordPress is primarily a blogging system it can be used as a CMS through Pages and Page Templates. WordPress offers many advantages, in the development side it has extended documentation and easy-to-use plugins that help you to quickly achieve results, for the end user it has a user-friendly back office, that allows them to manage an entire website with no hassle.

Deploy
Finally we launch the website! We put everything in the server, install WordPress, load the database, setup the website and do some more testing. It’s now out on the open.

So, what’s your website development process?

Rui Alves on July 13th, 2009

Web Development

0
 

Last day… João Lopes

Hoje foi o último dia do João Lopes na RUPEAL.

O João decidiu abraçar um novo desafio profissional e não podíamos deixar de partilhar aqui este acontecimento.

João, foi um grande privilégio acolher-te na nossa equipa e um prazer por termos acompanhado a tua evolução. Com certeza que o futuro ainda tem muito mais para te dar.

Com a tua dedicação e comprometimento, temos a certeza que conseguirás atingir todos os teus objectivos!

Em nome da equipa da RUPEAL, desejamos-te as maiores felicidades nesta nova etapa!

Rui Alves on July 10th, 2009

People

1
 

Jorge Silva

Gostaria de dar as boas-vindas ao Jorge Silva que integrou a equipa da RUPEAL esta semana. O Jorge é licenciado em Engenharia Informática pela UAL e, neste momento, prepara-se para integrar um projecto em .NET na área de Telecomunicações.

Bem-vindo a bordo!!

Rui Alves on July 9th, 2009

People

0
 

One user – Multiple accounts

One of the new features we have for the next release of InvoicExpress is to allow a user to be a member of multiple accounts.

The advantage of this model is that you only need one login credential to use all the accounts that you have access to.

In this post we show you a glimpse of our development process while developing this feature.

Our starting data model was (simplified here for clarity), a user belongs to an account, an account has many users, a user has many roles, nothing fancy.

class Account < ActiveRecord::Base
  has_many :users
end

class User < ActiveRecord::Base
  belongs_to :account
  has_and_belongs_to_many :roles
end

class Roles < ActiveRecord
  has_and_belongs_to_many :users
end

Users, Accounts and Memberships

The most obvious change is that the relation between user and account evolves from a one-to-many to many-to-many.

This change means user roles now have to be scoped by account. This isn’t easy with a regular many-to-many association.

In plain english we say “a user is a member of an account”. Member? We don’t have that in our data model. The relation between a user and its account is called Membership. Naming this showed us the missing link between a user and its accounts.

So we add a Membership model to map the relation between a user and it’s account.

User roles are now associated to an account through a membership.

class Account < ActiveRecord::Base
  belongs_to :o wner, :class_name => "User",
                     :foreign_key => "owner_id" 

  has_many :memberships, :dependent => :destroy
  has_many :users,:through => :memberships

end

class User<; ActiveRecord::Base
  has_many :memberships
  has_many :accounts, :through => :memberships,
                      :uniq => true
end

class Membership < ActiveRecord::Base
  belongs_to :user
  belongs_to :account

  has_and_belongs_to_many :roles
end

class Roles < ActiveRecord::Base
end

Keeping track

With multiple accounts per user we need know the currently used account. Our choice was to do it at the database level, because it would imply the least changes to our code base.

Knowing the current account means we also know the current membership. User roles can now be scoped to the current membership.

class User < ActiveRecord::Base

  has_many :memberships
  has_many :accounts, :through => :memberships,
                                   :uniq => true

  belongs_to :current_account, :class_name => "Account"
  has_one :current_membership,
          :class_name => "Membership",
          :foreign_key => "user_id",
          :conditions => 'current_account_id = #{self.current_account.id}'

  def roles
    self.current_membership.roles unless current_membership.blank?
  end
end

And that’s it for the data model changes

Changing accounts

Having multiple accounts, the user needs to know which one he is currently working on, as well as, be able to easily select another account.

For this double duty, we chose to use a always visible combo box located on the header of InvoicExpress.

The following code samples are simplified for readability.

Here we create a select input on our header partial and wire the onChange event to an ajax call to the users_controller.

# _header.html.erb
...
<%if current_user.accounts.count > 1 -%>;
  <%= select "change",:account, current_user.accounts.map{|a| [a.name, a.id]},
                                {:selected => current_user.account.id},
                                :o nchange => change_account
  %>
<% end -%>
...
# application_helper.rb
...
def change_account
  remote_function(:url => change_current_account_path, :method => :post,
                  :with =>"$('change_account').serialize()"
                 )
end

The change_current_account action fetches the selected account from the accounts the user is a member of.

If none is found the save will fail and we return a 412 – Precondition Failed error. On a successful save the user is now scoped the selected account, and we just have to redirect to the selected account account home screen.

# user_controller.rb
...
def change_current_account
  current_user.current_account = current_user.accounts.find(params[:change][:account])

  respond_to do |format|
    if current_user.save
      flash[:notice] = "You are now using account: #{account.name}"
      format.js do
        render :update do |page|
           page.redirect_to home_url
        end
      end
    else
        format.js{render :text => "change account error", :status =>; 412}
    end
  end
end

Wrapping up

Some say that every programming problem can be solved by another layer of indirection.
Others say that naming things is the hardest part of programming, and in this case both were true.

After we acknowledged and named the relation between a user and its accounts as a membership, all issues found almost resolved themselves. We were following a clear path. We were on rails after all.

Ps: In case you’re wondering the plugins we’re using for authentication and authorization are:

both available on github

Bruno Coelho on July 3rd, 2009

Software Development

0