commit 6a19f057ecfb431daeffdbe19ef69ffc351104a5 Author: Cédric Krier Date: Wed Mar 12 18:10:46 2008 +0100 Initial commit with currency diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000000..d1c055bc4a --- /dev/null +++ b/__init__.py @@ -0,0 +1,27 @@ +# Copyright (c) 2007 Cedric Krier. +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contact a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +from currency import * +from account import * diff --git a/__tryton__.py b/__tryton__.py new file mode 100644 index 0000000000..377e0aad44 --- /dev/null +++ b/__tryton__.py @@ -0,0 +1,18 @@ +{ + 'name': 'Account', + 'version': '0.1', + 'author': 'B2CK', + 'email': 'info@b2ck.com', + 'website': 'http://www.tryton.org/', + 'category': 'Generic Modules', + 'description': 'Financial and Accounting Module', + 'depends': [ + 'ir', + 'res', + 'company', + ], + 'xml': [ + 'account.xml', + 'currency.xml', + ], +} diff --git a/account.py b/account.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/account.xml b/account.xml new file mode 100644 index 0000000000..ed7f0d40a9 --- /dev/null +++ b/account.xml @@ -0,0 +1,18 @@ + + + + + Account + + + Account admin + + + + + + + + diff --git a/currency.py b/currency.py new file mode 100644 index 0000000000..4b54ef3cb9 --- /dev/null +++ b/currency.py @@ -0,0 +1,137 @@ +"Currency" + +from trytond.osv import fields, OSV, ExceptOSV +import time + + +class Currency(OSV): + 'Currency' + _name = 'account.currency' + _description = __doc__ + _order = 'code' + name = fields.Char('Name', size=128, required=True, translate=True) + code = fields.Char('Code', size=3, required=True) + rate = fields.Function('get_rate', string='Current rate', digits=(12, 6)) + rates = fields.One2Many('account.currency.rate', 'currency', 'Rates') + rounding = fields.Numeric('Rounding factor', digits=(12, 6)) + active = fields.Boolean('Active') + + def default_active(self, cursor, user, context=None): + return True + + def default_rounding(self, cursor, user, context=None): + return 0.01 + + def name_search(self, cursor, user, name, args=None, operator='ilike', + context=None, limit=None): + if args is None: + args = [] + args_name = args[:] + args_code = args[:] + if name: + args_name += [(self._rec_name, operator, name)] + args_code += [('code', operator, name)] + ids = self.search(cursor, user, args_code, limit=limit, context=context) + if len(ids) != 1: + ids += self.search(cursor, user, args_name, limit=limit, + context=context) + res = self.name_get(cursor, user, ids, context=context) + return res + + def get_rate(self, cursor, user, ids, name, arg, context=None): + ''' + Return the rate at the date from the context or the current date + ''' + res = {} + rate_obj = self.pool.get('account.currency.rate') + if context is None: + context = {} + date = context.get('date', time.strftime('%Y-%m-%d')) + for currency_id in ids: + rate_ids = rate_obj.search(cursor, user, [ + ('currency', '=', currency_id), + ('date', '<=', date), + ], limit=1, order='date DESC') + if rate_ids: + res[currency_id] = rate_ids[0] + else: + res[currency_id] = 0.0 + rate_ids = [x for x in res.values() if x] + rates = rate_obj.browse(cursor, user, rate_ids, context=context) + id2rate = {} + for rate in rates: + id2rate[rate.id] = rate + for currency_id in res.keys(): + if res[currency_id]: + res[currency_id] = id2rate[res[currency_id]].rate + return res + + def round(self, cursor, user, currency, amount): + 'Round the amount depending of the currency' + return round(amount / currency.rounding) * currency.rounding + + def is_zero(self, cursor, user, currency, amount): + 'Return True if the amount can be considered as zero for the currency' + return abs(self.round(cursor, user, currency, amount)) < currency.rounding + + def compute(self, cursor, user, from_currency_id, amount, to_currency_id, + round=True, context=None): + ''' + Take a currency id and an amount + Return the amount to the new currency + Use the rate of the date of the context or the current date + ''' + from_currency = self.browse(cursor, user, from_currency_id, context=context) + to_currency = self.browse(cursor, user, to_currency_id, context=context) + if (not from_currency.rate) or (not to_currency.rate): + date = context.get('date', time.strftime('%Y-%m-%d')) + if not from_currency.rate: + name = from_currency.name + else: + name = to_currency.name + raise ExceptOSV('UserError', 'No rate found \n' \ + 'for the currency: %s \n' \ + 'at the date: %s' % (name, date)) + if to_currency == from_currency: + if round: + return self.round(cursor, user, to_currency, amount) + else: + return amount + else: + if round: + return self.round(cursor, user, to_currency, + amount * to_currency.rate / from_currency.rate) + else: + return amount * to_currency.rate / from_currency.rate + +Currency() + + +class Rate(OSV): + 'Rate' + _name = 'account.currency.rate' + _description = __doc__ + _rec_name = 'date' + _order = 'date DESC' + date = fields.Date('Date', required=True, select=1) + rate = fields.Numeric('Rate', digits=(12, 6), required=1) + currency = fields.Many2One('account.currency', 'Currency') + + def __init__(self): + super(Rate, self).__init__() + self._sql_constraints = [ + ('date_currency_uniq', 'UNIQUE(date, currency)', + 'A currency can only have one rate by date!'), + ] + + def default_date(self, cursor, user, context=None): + return time.strftime('%Y-%m-%d') + +Rate() + + +class Company(OSV): + _name = 'company.company' + currency = fields.Many2One('account.currency', 'Currency', required=True) + +Company() diff --git a/currency.xml b/currency.xml new file mode 100644 index 0000000000..146c3ddcea --- /dev/null +++ b/currency.xml @@ -0,0 +1,149 @@ + + + + + account.currency + form + + + + + account.currency + tree + + + + + + + + ]]> + + + + Currencies + account.currency + form + + + + + + + + + + + + + + + + + + + + + + + + + + + + + company.company + + + + + + + ]]> + + + + company.company + + + + + + + + ]]> + + + + + + + + + + + + + + + + + + + Euro + EUR + + + + + + + + + United States dollar + USD + + + + Swiss franc + CHF + + + + diff --git a/setup.py b/setup.py new file mode 100644 index 0000000000..5aba20bcbf --- /dev/null +++ b/setup.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python + +from distutils.core import setup +from distutils.command import sdist + + +class mysdist(sdist.sdist): + + def add_defaults(self): + sdist.sdist.add_defaults(self) + if self.distribution.has_pure_modules(): + build_py = self.get_finalized_command('build_py') + data = [] + for package in build_py.packages: + src_dir = build_py.get_package_dir(package) + data.extend(build_py.find_data_files(package, src_dir)) + self.filelist.extend(data) + +info = eval(file('__tryton__.py').read()) + +requires = ['trytond'] + ['trytond-' + x for x in info.get('depends', [])] + +setup(name='trytond-' + info['name'].lower(), + version=info.get('version', '0'), + description=info.get('description', ''), + author=info.get('author', ''), + author_email=info.get('email', ''), + url=info.get('website', ''), + package_dir={'trytond.modules.' + info['name'].lower(): '.'}, + packages=[ + 'trytond.modules.' + info['name'].lower(), + ], + package_data={ + 'trytond.modules.' + info['name'].lower(): info.get('xml', []), + }, + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Environment :: Plugins', + 'Intended Audience :: Developers', + 'Intended Audience :: Financial and Insurance Industry', + 'Intended Audience :: Legal Industry', + 'Natural Language :: English', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Topic :: Office/Business', + 'Topic :: Office/Business :: Financial :: Accounting', + ], + license=info.get('license', 'GPL-2'), + #requires=requires, + cmdclass={ + 'sdist': mysdist, + }, +)