Enable Dark Mode!
sftp-transfer-odoo-12.png
By: Hajaj Roshan

SFTP Transfer in Odoo 12

Technical Odoo 12

Odoo deals with multiple business documents such as invoices, bills and many other. No matter what kind of reports, one can backup these business documents into a server using the SFTP transfer protocol in Odoo. 


SFTP Transfer Protocol


SFTP stands for Secure File Transfer Protocol. SFTP transfer protocol is one of the most popular and secure methods of file transfer between two remote systems. It comes within the SSH, however, works in a separate package over a secured connection. SFTP is always preferred over FTP (File Transfer Protocol) because of SFTP’s underlying security features and its ability to piggy-back on an SSH connection. The default port number of SFTP protocol is port 22.


In order to transfer files to a remote server, we are using python library pysftp.


Before using the library, one must ensure that it is installed in your system.

pip3 install pysftp 


Then Import pysftp

import pysftp


To test connection:

my_host = "local ip address"
my_username = "user"
my_password = "password"
with pysftp.Connection(host=my_host, username=my_username, password=my_password) as sftp:
print "Connection succesfully established ... "


If the connection is successfully established, set the remote location path and local file path.

remote_path = '/var/sftp/file/'
local_path =  './file.pdf'


Then pass the variables in sftp.put()

sftp.put(local_path, remote_path)

the connection will automatically close at the end of the with-block.


In odoo, we are using the same python library pysftp.


Create a module for SFTP backup. Create a model for SFTP configuration.

from odoo import models, fields, api
from odoo.exceptions import Warning
import base64
import tempfile
import os
try:
   import pysftp
except ImportError:
   raise ImportError(
       'This module needs pysftp to automatically write backups to the FTP through SFTP. Please install pysftp '
       'on your system. (sudo pip3 install pysftp)')
class FileBackup(models.Model):
   _name = 'sftp.backup'
   _rec_name = 'sftp_host'
   sftp_host = fields.Char(string="Host", required=True)
   sftp_path = fields.Char("Backup Directory Path", required=True)
   sftp_user = fields.Char("Username", required=True)
   sftp_password = fields.Char("Password", required=True)
   sftp_hostkeys = fields.Char("Hostkeys")


Create a button in the configuration form for testing connection.

       <!-- Form View of SFTP Configuration -->
       <record id="sftp_config_view" model="ir.ui.view">
           <field name="name">backup.sftp.conf</field>
        <field name="model">sftp.backup</field>
        <field name="arch" type="xml">
               <form>
                   <header>
                       <button name='sftp_test_connection' string="SFTP Test Connection" type="object" class="oe_highlight" groups="base.group_user"/>
                   </header>
                   <sheet>
                       <group name="" style="width:80%;">
                           <field name="sftp_host"/>
                           <field name="sftp_user"/>
                           <field name="sftp_password"/>
                           <field name="sftp_path"/>
                           <field name="sftp_hostkeys"/>
                       </group>
                   </sheet>
               </form>
           </field>
       </record>
   </data>
</odoo>

sftp-transfer-odoo-12-cybrosys


To test the connection with SFTP server:
def sftp_test_connection(self):
   self.ensure_one()
   for rec in self:
       file_path = rec.sftp_path
       ip_host = rec.sftp_host
       username_login = rec.sftp_user
       password_login = rec.sftp_password
       hostkeys = rec.sftp_hostkeys
       if hostkeys:
           cnopts = pysftp.CnOpts()
           cnopts.hostkeys.load(hostkeys)
       else:
           cnopts = pysftp.CnOpts()
           cnopts.hostkeys = None
       # Connect with external server over SFTP, so we know sure that everything works.
       try:
           with pysftp.Connection(host=ip_host, username=username_login, password=password_login, cnopts=cnopts) as sftp:
               sftp.cwd(file_path)
       except Exception as e:
           raise Warning('There was a problem connecting to the remote ftp: ' + str(e))
       raise Warning("Connection Success!!!")

sftp-transfer-odoo-12-cybrosys


If the connection gets established,  you can backup your file to SFTP server. 


Here, taking the example of SFTP transfer of the PDF file of each invoice. So first stored all the pdf invoices into a binary field pdf and boolean field transfer in model ‘account.invoice’.


Then defined a function for SFTP transfer.


def sftp_backup(self):
   conf_ids = self.search([])
   invoices = self.env['account.invoice'].search([])
   for rec in conf_ids:
       try:
           # Store all values in variables
           path = rec.sftp_path
           ip_host = rec.sftp_host
           username = rec.sftp_user
           password = rec.sftp_password
           hostkeys = rec.sftp_hostkeys
           if hostkeys:
               cnopts = pysftp.CnOpts()
               cnopts.hostkeys.load(hostkeys)
           else:
               cnopts = pysftp.CnOpts()
               cnopts.hostkeys = None
           # Establishing connection with SFTP Server
           with pysftp.Connection(host=ip_host, username=username, password=password) as sftp:
               for inv in invoices:
                   # Check the invoices which have pdf files and which files are not transferred before
                   if inv.pdf and inv.transfer is False:
                       try:
                           # creating temporary files to store the transferring file
                           temp = tempfile.NamedTemporaryFile(mode='w+t')
                           temp.writelines(base64.decodestring(inv.pdf).decode('utf-8'))
                           temp.seek(0)
                           filename = inv.pdf_name
                           # transfer file, specify the path and file name
                           try:
                               sftp.put(temp.name, os.path.join(path, filename))
                               inv.transfer = True
                           except Exception as e:
                               raise Warning('Exception! We couldn\'t back up to the SFTP server..' + str(e))
                       finally:
                           temp.close()
       except Exception as e:
           raise Warning('Exception! We couldn\'t back up to the SFTP server..' + str(e))


If you need any assistance in odoo, we are online, please chat with us.



0
Comments



Leave a comment



whatsapp_icon
location

Calicut

Cybrosys Technologies Pvt. Ltd.
Neospace, Kinfra Techno Park
Kakkancherry, Calicut
Kerala, India - 673635

location

Kochi

Cybrosys Technologies Pvt. Ltd.
1st Floor, Thapasya Building,
Infopark, Kakkanad,
Kochi, India - 682030.

location

Bangalore

Cybrosys Techno Solutions
The Estate, 8th Floor,
Dickenson Road,
Bangalore, India - 560042

Send Us A Message