[RUBY] If you issue a freeeAPI invoice, let's do + update automatically! !!

Hello, this is mk, which is aimed at engineers change jobs from inexperienced. This time I touched the freee API.

As the title suggests, uploading an invoice and updating it every time is a hassle, so I wrote a program in Ruby that issues an invoice via API and does everything up to + update.

github

environment

macOS 10.15.5 ruby 2.7.1

First of all, what is + update?

How to use freee when advance reception occurs (external link) This article is organized in an easy-to-understand manner, In short, it is a button that allows you to change the advance payment to sales. (I appologize if I am mistaken,,,)

There is a freee pre-order management app in the freee app store. I created this because I wanted to automate the work of dividing the sales received n months before the issuance of the invoice into monthly sales from scratch.

Required processing

--Issuing an access token (GET) --Get company_id (GET) --Get account id (GET) --Getting the customer id (GET) --Get tax classification id (GET) --Invoicing (POST) --Get transaction details (GET) * Get transaction line id -+ Create Update (POST)

Invoicing → + update code

First, we will describe helper-like processing.

helper.rb


#Month processing
def add_month(num)
  if num < 12
    return num = num + 1
  elsif num == 12
    num = 1
  end
end

#Processing to find the positive renewal amount for the first month
def first_price(price,times)
  (price % times) + (price / times)
end

Define add_month because you have to get the end of the update count month including the invoice issuance month.

Also, if the billing amount is not divisible by the number of updates, define first_price to include the remainder in the first update.

Module that specifies the header of the http request

set_header.rb



module Header
  def self.get_header
    headers = {
      "accept" => "application/json",
      "Authorization"=> "Bearer #{YOUR_ACCESS_TOKEN}"
    }
  end
  def self.post_header
    headers = {
      "accept" => "application/json",
      "Authorization"=> "Bearer #{YOUR_ACCESS_TOKEN}",
      "Content-Type" => "application/json"
    }
  end
end

Invoicing code

invoice.rb



require 'set_header.rb'
require 'json'
require 'net/http'

class Invoice
  BASE_URL = 'https://api.freee.co.jp'
  #Create an invoice by passing parameters as arguments
  def self.make_invoice(params)
    uri = URI.parse(BASE_URL + '/api/1/invoices')
    http = Net::HTTP.new(uri.host,uri.port)
    http.use_ssl = uri.scheme === "https"
    req = Net::HTTP::Post.new(uri.path)
    req.body = params.to_json
    req.initialize_http_header(Header.post_header)
    response = http.request(req)
    res_hash = JSON.parse(response.body)
  end
end

Plus update creation code

koushin.rb



require_relative 'set_header.rb'
require 'json'
require 'net/http'

class Koushin
  BASE_URL = 'https://api.freee.co.jp'
  #Transaction id,Apply a plus update by passing a parameter as an argument
  def self.post_koushin(torihiki_id,params)
    uri = URI.parse(BASE_URL + "/api/1/deals/#{torihiki_id}/renews")
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = uri.scheme === "https"
    req = Net::HTTP::Post.new(uri.path)
    req.body = params.to_json
    req.initialize_http_header(Header.post_header)
    response = http.request(req)
    res_hash = JSON.parse(response.body)
  end
end

And implement from invoicing to plus renewal Billed amount is 12345678 yen (excluding tax), tax rate is 10%

invoice_koushin.rb


require 'invoice.rb'
require 'koushin.rb'
require 'date'
require 'helper.rb'
#Other various requirements are required, but omitted

#Setting required items
month = Time.now.month
year = Time.now.year
count = 1
company_id = Company.company_id #See github Get office id

#Billing amount(Tax exemption)
amount = 12345678
#consumption tax(10%)
vat = (amount * 0.1).floor
#+Number of updates
num = 12


#Invoice parameters
invoice_params = {
  "company_id": company_id,
  "issue_date": Date.today,
  "due_date": Date.new(year, month, -1),
  "partner_id": Supplier.supplier_id('CFO'), #See github Get account id
  "booking_date": Date.today,
  "description": "#{Date.today.month}Monthly invoice",
  "invoice_status": "issue",
  "partner_display_name": "CFO Co., Ltd.",
  "partner_title": "You",
  "partner_contact_info": "Sales staff",
  "partner_zipcode": "012-0009",
  "partner_prefecture_code": 4,
  "partner_address1": "Yuzawa City",
  "partner_address2": "Building A",
  "company_name": "freee Co., Ltd.",
  "company_zipcode": "000-0000",
  "company_prefecture_code": 12,
  "company_address1": "XX Ward YY1-1-1",
  "company_address2": "Building 1F",
  "company_contact_info": "Corporate sales representative",
  "payment_type": "transfer",
  "payment_bank_info": "XX Bank YY Branch 1111111",
  "message": "We will charge you as follows.",
  "notes": "Thank you every time",
  "invoice_layout": "default_classic",
  "tax_entry_method": "exclusive",
  "invoice_contents": [
    {
      "order": 0,
      "type": "normal",
      "qty": 1,
      "unit": "Pieces",
      "unit_price": amount,
      "vat": vat,
      "description": "Remarks",
      "tax_code": 2,
      "account_item_id": AccountItem.account_item_id('Unearned revenue') #github参照 Unearned revenueのaccount_item_Get id
    }
  ]
}

#Issuance of invoices
invoice = Invoice.make_invoice(invoice_params)
puts 'Issued an invoice'
#Get transaction id from invoice issuance response
torihiki_id = invoice['invoice']['deal_id']
#Get the transaction line id of the above transaction id
renew_target_id = Torihiki.target_id(torihiki_id) #See github torihiki_Get the details of the transaction associated with the id, and get the transaction line id from there
#+Account id at update(amount of sales)Get
uriagedaka_id = AccountItem.account_item_id('amount of sales') #See github

#Transaction id num times using transaction line id+Update
num.times do
  #When count is 1+Renewal amount first_Change to price
  if count == 1
    koushin_amount = first_price(amount,num)
    koushin_vat = first_price(vat,num)
  else
    koushin_amount = amount / num
    koushin_vat = vat / num
  end

  date = Date.new(year, month, -1) 
#+Set update parameters
  koushin_params = {
    "company_id": company_id,
    "update_date": date,
    "renew_target_id": renew_target_id,
    "details": [
      {
        "account_item_id": uriagedaka_id,
        "tax_code": 21,
        "amount": (koushin_amount + koushin_vat),
        "vat": koushin_vat
      }
    ]
  }
  #Transaction id,With parameters+Create update
  Koushin.post_koushin(torihiki_id,koushin_params)
  puts "#{date}Was updated"
  #Get the month of the next month
  month = add_month(month)
  #If month is January, add 1 year
  year += 1 if month == 1
  count += 1
end

Try running it locally.

スクリーンショット 2020-07-15 20.01.48.png

The process seems to have run properly. Execution time is about 5 seconds (a little long ...) Let's take a look at accounting freee.

スクリーンショット 2020-07-15 19.54.43.png

You can issue an invoice to CFO Co., Ltd.! The amount and consumption tax amount are included properly. スクリーンショット 2020-07-15 22.06.04.png Next, let's look at transactions.

スクリーンショット 2020-07-15 19.53.04.png The amount after the update is 0 yen! スクリーンショット 2020-07-15 19.52.21.png

The update date also includes the last day of 12 months, including the end of the issue month.

Future tasks

I would like to improve the invoice issued at the end of the month so that I can respond flexibly, such as what to do, I want to update from the month after the transfer is confirmed. It also allows you to import each invoice parameter and update count in csv. And the code isn't beautiful ... lol

Dedicated every day

Recommended Posts

If you issue a freeeAPI invoice, let's do + update automatically! !!
What to do if you accidentally create a model
What to do if you get a java.io.IOException in GlassFish
If you have complicated calculations, let's create a CalcRule class
What to do if you get a gcc error in Docker
What to do if you get a DISPLAY error in gym.render ()
What to do if you get a groovy warning in Thymeleaf Layout
What to do if you get a MiniMagick vulnerability alert on GitHub
What to do if you install Ubuntu
What to do if you get a SQLite3 :: BusyException: database is locked error