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, apifrom odoo.exceptions import Warningimport base64import tempfileimport ostry:import pysftpexcept 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>
def sftp_test_connection(self):self.ensure_one()for rec in self:file_path = rec.sftp_pathip_host = rec.sftp_hostusername_login = rec.sftp_userpassword_login = rec.sftp_passwordhostkeys = rec.sftp_hostkeysif 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!!!")
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 variablespath = rec.sftp_pathip_host = rec.sftp_hostusername = rec.sftp_userpassword = rec.sftp_passwordhostkeys = rec.sftp_hostkeysif hostkeys:cnopts = pysftp.CnOpts()cnopts.hostkeys.load(hostkeys)else:cnopts = pysftp.CnOpts()cnopts.hostkeys = None# Establishing connection with SFTP Serverwith 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 beforeif inv.pdf and inv.transfer is False:try:# creating temporary files to store the transferring filetemp = 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 nametry:sftp.put(temp.name, os.path.join(path, filename))inv.transfer = Trueexcept 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))