<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>app/models/invoice.rb</filename>
    </added>
    <added>
      <filename>db/migrate/20090531151034_create_invoices.rb</filename>
    </added>
    <added>
      <filename>lib/pdfwritter_extensions.rb</filename>
    </added>
    <added>
      <filename>public/images/invoice_header.jpg</filename>
    </added>
    <added>
      <filename>public/images/invoice_header.png</filename>
    </added>
    <added>
      <filename>test/functional/invoices_controller_test.rb</filename>
    </added>
    <added>
      <filename>test/unit/invoice_test.rb</filename>
    </added>
    <added>
      <filename>test/unit/pdf_generator_test.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -11,4 +11,6 @@ public/resources/*
 test/performance/tmp/
 public/paper_files
 public/paper_photos
+public/invoices
+tmp/invoices
 certs/*pem</diff>
      <filename>.gitignore</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,17 @@
 class InvoicesController &lt; ApplicationController
+  before_filter :login_required 
+  
   def create
-    @cart = Cart.find( params[:id] )
+    puts &quot;XXX: create&quot;
+    @cart = Cart.find( params[:id] )                if admin?
+    @cart = current_user.carts.find( params[:id] )  if !admin?
+    
+    record_not_found and return  unless @cart.is_purchased?
+    record_not_found and return  unless @cart.invoice.nil?
+    
+    Invoice.print( @cart )
+    flash[:notice] = 'Invoice created successfully, please use the link bellow to download it.'
+    
     redirect_to :controller =&gt; 'carts', :action =&gt; 'show', :id =&gt; @cart
   end
 end
\ No newline at end of file</diff>
      <filename>app/controllers/invoices_controller.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,6 +3,8 @@ class Cart &lt; ActiveRecord::Base
   has_many :events, :through =&gt; :carts_events
   
   belongs_to :user
+
+  has_one :invoice
   
   serialize :paypal_notify_params
   serialize :paypal_complete_params</diff>
      <filename>app/models/cart.rb</filename>
    </modified>
    <modified>
      <diff>@@ -23,11 +23,9 @@
 &lt;h4&gt;Invoice info&lt;/h4&gt;
 &lt;p&gt;&lt;%= simple_format(@cart.invoice_info) %&gt;&lt;/p&gt;
 
-&lt;!--
 &lt;h4&gt;Invoice&lt;/h4&gt;
 &lt;% if @cart.invoice %&gt;
-  &lt;%= link_to 'Download invoice', @cart.invoice %&gt;
+  &lt;%= link_to 'Download invoice', @cart.invoice.url_path %&gt;
 &lt;% else %&gt;
-  &lt;%= link_to 'Download invoice', invoices_path( :id =&gt; @cart.id ), :method =&gt; 'post'  %&gt;
+  &lt;%= link_to 'Create invoice', invoices_path( :id =&gt; @cart.id ), :method =&gt; 'post'  %&gt;
 &lt;% end %&gt;
---&gt;</diff>
      <filename>app/views/carts/show.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -11,6 +11,10 @@ test:
   twitter_user: pepe
   twitter_pass: pepe
   twitter_notification_step: 1
+  tax_percent: 16
+  seller_invoice_info: &quot;Name Company \nAddress Company with &#233;xtra&#241;os car&#225;cteres \nG65037772&quot;
+  invoices_pdf_path: /tmp/invoices
+  invoices_serial_prefix: euruko-2009-
   
 development:
   site_domain: 127.0.0.1:3000
@@ -25,7 +29,11 @@ development:
   twitter_user: pepe
   twitter_pass: pepe
   twitter_notification_step: 1
-  
+  tax_percent: 16
+  seller_invoice_info: &quot;Name Company \nAddress Company with &#233;xtra&#241;os car&#225;cteres \nG65037772&quot;
+  invoices_pdf_path: /public/invoices
+  invoices_serial_prefix: euruko-2009-
+    
 production:
   site_domain: eurukostaging.fernandoguillen.info
   site_name: EuRuKo
@@ -38,4 +46,8 @@ production:
   yahoo_id: qvONq5jV34GLKDBadNyEtXoS9dR22TK1gacPRBXZqqXrAfwCYUd6fMMIze9zIbWe9a7juSXIGlfH
   twitter_user: pepe
   twitter_pass: pepe
-  twitter_notification_step: 1
\ No newline at end of file
+  twitter_notification_step: 1
+  tax_percent: 16
+  seller_invoice_info: &quot;Spanish Ruby Users Group \nTravessera de les Corts 48, Sobre&#225;tico 2a \n08903 L'Hospitalet de Llobregat \nBarcelona (Spain) \nG65037772&quot;
+  invoices_pdf_path:  /public/invoices
+  invoices_serial_prefix: euruko-2009-</diff>
      <filename>config/config.yml</filename>
    </modified>
    <modified>
      <diff>@@ -2,4 +2,8 @@ require 'utils'
 require 'paperclip_validations_extended'
 require 'will_paginate'
 require 'pdf/writer'
-require 'bluecloth'
\ No newline at end of file
+require 'pdf/simpletable'
+require 'bluecloth'
+
+# extensions
+require 'pdfwritter_extensions'
\ No newline at end of file</diff>
      <filename>config/initializers/requires.rb</filename>
    </modified>
    <modified>
      <diff>@@ -21,6 +21,7 @@ TODOs
 * &quot;Meanwhile on the others tracks:&quot;
 * Exportar PDF de las charlas
 * Editor static pages
+* Campo serial de invoice deber&#237;a tener el serial completo no s&#243;lo el entero: euruko-2009-0001
 
 ## xuanxu:
 * Pantalla &#250;ltimos comentarios</diff>
      <filename>doc/TODO.md</filename>
    </modified>
    <modified>
      <diff>@@ -9,4 +9,97 @@ class PDFGenerator
     end
     pdf.render
   end
+  
+  def self.create_pdf_invoice( invoice )
+    pdf = PDF::Writer.new(:paper =&gt; &quot;A4&quot;)
+    pdf.margins_pt(36, 54)
+    pdf.select_font( &quot;Times-Roman&quot; )
+    
+    pdf.image( &quot;#{RAILS_ROOT}/public/images/invoice_header.jpg&quot; )
+    
+    # pdf.add_text_wrap( 100, pdf.y, 150, &quot;#{APP_CONFIG[:seller_invoice_info]}&quot;, 14, :right )
+    pdf.text( APP_CONFIG[:seller_invoice_info], :font_size =&gt; 14, :left =&gt; 250, :justification =&gt; :left )
+    
+    pdf.move_pointer( 50 )
+    pdf.text( &quot;Invoice ID: &lt;b&gt;#{APP_CONFIG[:invoices_serial_prefix]}#{invoice.serial}&lt;/b&gt;&quot; )
+    pdf.text( &quot;Date: &lt;b&gt;#{invoice.date.strftime( '%d of %b of %Y' )}&lt;/b&gt;&quot; )
+    pdf.text( &quot;To:&quot;, :top =&gt; 1000 )
+    
+    if invoice.cart.invoice_info
+      invoice.cart.invoice_info.each_line do |line|
+        pdf.text( &quot;#{line}&quot; )
+      end
+    end
+
+    #
+    # TABLE
+    # 
+    pdf.move_pointer( 50 )
+    table_elements = PDF::SimpleTable.new     
+    table_elements.data = []
+    invoice.cart.events.each do |event|
+      # puts &quot;XX: event: #{event}&quot;
+      table_elements.data &lt;&lt; { &quot;concept&quot; =&gt; event.name, &quot;price&quot; =&gt; Utils.cents_to_euros(Utils.total_without_tax(event.price_cents)) }
+    end
+    
+    if invoice.cart.events.empty?
+      table_elements.data &lt;&lt; { &quot;concept&quot; =&gt; &quot;&quot;, &quot;price&quot; =&gt; &quot;0&quot; }
+    end
+    
+    table_elements.column_order = [ &quot;concept&quot;, &quot;price&quot; ]
+    
+    table_elements.columns[&quot;concept&quot;] = 
+      PDF::SimpleTable::Column.new(&quot;concept&quot;) { |col| 
+        col.heading = &quot;Concept&quot; 
+        col.justification = :left
+        col.width = 350
+      }
+      
+    table_elements.columns[&quot;price&quot;] = 
+      PDF::SimpleTable::Column.new(&quot;price&quot;) { |col| 
+        col.heading = &quot;Price&quot; 
+        col.justification = :right
+        col.width = 100
+      }
+    
+    table_elements.font_size     = 20
+    table_elements.position      = 90 
+    table_elements.orientation   = :right 
+    # table_elements.width         = 550
+    table_elements.render_on( pdf )
+    
+    table_totals = PDF::SimpleTable.new
+    table_totals.data = [
+      { &quot;concept&quot; =&gt; &quot;Total&quot;, &quot;price&quot; =&gt; Utils.cents_to_euros(Utils.total_without_tax(invoice.cart.total_price)) },
+      { &quot;concept&quot; =&gt; &quot;Tax #{APP_CONFIG[:tax_percent]}%&quot;, &quot;price&quot; =&gt; Utils.cents_to_euros(Utils.total_tax(invoice.cart.total_price)) },
+      { &quot;concept&quot; =&gt; &quot;&lt;b&gt;Total + Tax&lt;/b&gt;&quot;, &quot;price&quot; =&gt; Utils.cents_to_euros( invoice.cart.total_price ) }
+    ]
+    table_totals.column_order = [ &quot;concept&quot;, &quot;price&quot; ]
+    
+    table_totals.columns[&quot;concept&quot;] = 
+      PDF::SimpleTable::Column.new(&quot;concept&quot;) { |col| 
+        col.heading = &quot;Concept&quot; 
+        col.justification = :right
+        col.width = 350
+      }
+      
+    table_totals.columns[&quot;price&quot;] = 
+      PDF::SimpleTable::Column.new(&quot;price&quot;) { |col| 
+        col.heading = &quot;Price&quot; 
+        col.justification = :right
+        col.width = 100
+      }
+    
+    table_totals.font_size     = 20
+    table_totals.show_headings = false
+    table_totals.position      = 90 
+    table_totals.orientation   = :right 
+    # table_totals.width         = 550
+    table_totals.render_on( pdf )
+    
+    FileUtils.mkdir_p( File.dirname( invoice.path ) )
+    File.open( invoice.path, 'w' ) { |f| f.write( pdf.render ) }
+    
+    puts &quot;XXX: printed invoice on: #{invoice.path}&quot;
+  end
 end
\ No newline at end of file</diff>
      <filename>lib/pdf_generator.rb</filename>
    </modified>
    <modified>
      <diff>@@ -11,4 +11,18 @@ class Utils
   def self.cents_to_euros( cents )
     Kernel.sprintf( &quot;%.2f&quot;, cents/100.0 )
   end
+  
+  def self.total_without_tax( cents )
+    return( 
+      (cents * 100).to_f / 
+      (100 + APP_CONFIG[:tax_percent].to_i) 
+    )
+  end
+  
+  def self.total_tax( cents )
+    return(
+      (cents * APP_CONFIG[:tax_percent].to_i).to_f / 
+      (100 + APP_CONFIG[:tax_percent].to_i) 
+    )
+  end
 end
\ No newline at end of file</diff>
      <filename>lib/utils.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1,31 @@
 Factory.define :room do |f|
   f.sequence(:name) { |n| &quot;room_name#{n}&quot;}
-end
\ No newline at end of file
+end
+
+Factory.define :invoice do |f|
+  f.association :cart, :factory =&gt; :cart
+  f.sequence(:serial) { |n| Kernel.sprintf( &quot;%3d&quot;, n ) }
+  f.sequence(:path) { |n| &quot;/tmp/path#{n}&quot; }
+  f.sequence(:date) { |n| Time.now + n }
+end
+
+Factory.define :cart do |f|
+  f.association :user, :factory =&gt; :user
+  f.status Cart::STATUS[:ON_SESSION] # no puedo hacer esto: Post::STATUS_PUBLISHED
+end
+
+Factory.define :event do |f|
+  f.sequence(:name) { |n| &quot;name#{n}&quot; }
+  f.sequence(:description) { |n| &quot;description#{n}&quot; }
+  f.sequence(:price_cents) { |n| n }
+end
+
+Factory.define :user do |f|
+  f.sequence(:login) { |n| &quot;login#{n}&quot; }
+  f.sequence(:name) { |n| &quot;name#{n}&quot; }
+  f.sequence(:email) { |n| &quot;email#{n}@example.com&quot; }
+  f.password &quot;password&quot;
+  f.password_confirmation &quot;password&quot;
+  f.role User::ROLE[:USER]
+  f.public_profile true
+end</diff>
      <filename>test/factories.rb</filename>
    </modified>
    <modified>
      <diff>@@ -137,4 +137,5 @@ class CartTest &lt; ActiveSupport::TestCase
     
     @cart.send_twitter_notifications
   end
+  
 end
\ No newline at end of file</diff>
      <filename>test/unit/cart_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,6 @@
-require 'utils'
-require 'test/unit'
+require File.dirname(__FILE__) + '/../test_helper'
 
-class UtilsTest &lt; Test::Unit::TestCase
+class UtilsTest &lt; ActiveSupport::TestCase
   def test_site_key_generator
     assert( Utils.site_key_generator )
     assert_not_equal( Utils.site_key_generator, Utils.site_key_generator )
@@ -12,4 +11,39 @@ class UtilsTest &lt; Test::Unit::TestCase
     assert_equal( &quot;123.04&quot;, Utils.cents_to_euros( 12304 ) )
     assert_equal( &quot;0.10&quot;, Utils.cents_to_euros( 10 ) )
   end
+  
+  def test_total_without_tax
+    [3000, 1000, 123].each do |q|
+      assert_equal( 
+        q * 100 / (100 + APP_CONFIG[:tax_percent].to_f), 
+        Utils.total_without_tax( q )
+      )
+    end
+  end
+  
+  def test_total_tax
+    [3000, 1000, 123].each do |q|
+      assert_equal( 
+        q * APP_CONFIG[:tax_percent].to_f / (100 + APP_CONFIG[:tax_percent].to_i), 
+        Utils.total_tax( q )
+      )
+    end
+  end
+  
+  def test_total_without_tax_add_to_total_tax_should_be_the_total
+    [3000, 1000, 123].each do |q|
+      assert_equal( 
+        q,
+        Utils.total_without_tax( q ) + Utils.total_tax( q )
+      )    
+    end
+  end
+  
+  def test_total_without_tax_on_euros_add_to_total_tax_on_euros_should_be_the_total_on_euros
+    [3000, 1000, 123].each do |q|
+      total_without_tax_on_euros = Utils.cents_to_euros( Utils.total_without_tax( q ) )
+      total_tax_on_euros = Utils.cents_to_euros( Utils.total_tax( q ) )
+      assert_equal( q.to_f/100, total_without_tax_on_euros.to_f + total_tax_on_euros.to_f )
+    end
+  end
 end
\ No newline at end of file</diff>
      <filename>test/unit/utils_test.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>ab7f1ff4bdf87da4fa21bc1a59b4b3c0c6fa8d6e</id>
    </parent>
  </parents>
  <author>
    <name>Fernando Guillen</name>
    <email>fguillen.mail@gmail.com</email>
  </author>
  <url>http://github.com/fguillen/euruko_app/commit/b7a08c66294951634dc922f469f5bf6bd931363e</url>
  <id>b7a08c66294951634dc922f469f5bf6bd931363e</id>
  <committed-date>2009-05-31T10:59:20-07:00</committed-date>
  <authored-date>2009-05-31T10:59:20-07:00</authored-date>
  <message>invoice generation</message>
  <tree>fe148a23070aa4500637c9e8cb2a65a56c9e7a2b</tree>
  <committer>
    <name>Fernando Guillen</name>
    <email>fguillen.mail@gmail.com</email>
  </committer>
</commit>
