← Back to team overview

openerp-expert-accounting team mailing list archive

Re: cash book / petty cash - Patch for 5.0

 

On Friday 16 April 2010 11:42:38 Borja López Soilán (Pexego) wrote:
> Ferdinand, (my fellow Manuel pointed out that) the patch has a small
> usability problem:
> 
> It doesn't ignore special periods (opening/closing periods), so if the
> date falls between a normal plus an special period dates (two periods
> are returned) it may return the special period.
Thanks for the hint 
Please test this one it checks for uniqueness of returned periods
> 
> Ferdinand Gassauer wrote:
> > Hello
> > I have created a patch for 5.0 "Entries by statement"

-- 
regards
Ferdinand Gassauer
ChriCar Beteiligungs- und Beratungs- GmbH
Official OpenERP Partner
--- /home/terp/OpenERP/official/addons/account/account_bank_statement.py	2010-02-23 08:06:40.836422174 +0100
+++ account_bank_statement.py	2010-04-16 23:12:59.277457675 +0200
@@ -25,11 +25,15 @@ from osv import fields, osv
 
 from tools.misc import currency
 from tools.translate import _
+from tools import config
 
 import mx.DateTime
 from mx.DateTime import RelativeDateTime, now, DateTime, localtime
 
 
+#----------------------------------------------------------------------------
+# Account Bank Statement
+#----------------------------------------------------------------------------
 class account_bank_statement(osv.osv):
     def _default_journal_id(self, cr, uid, context={}):
         if context.get('journal_id', False):
@@ -107,16 +111,24 @@ class account_bank_statement(osv.osv):
     _name = "account.bank.statement"
     _description = "Bank Statement"
     _columns = {
-        'name': fields.char('Name', size=64, required=True, states={'confirm': [('readonly', True)]}),
+        'name': fields.char('Name', size=64, required=True,
+            help ="Keep empty to use automated numbering",
+            states={'confirm': [('readonly', True)]}),
         'date': fields.date('Date', required=True,
+            help = "Date of bank statement, used to propose period",
             states={'confirm': [('readonly', True)]}),
         'journal_id': fields.many2one('account.journal', 'Journal', required=True,
+            help="""Create journals for every bank and cash account and associate yearly sequences
+Yearly numbering for banks works only if companies fiscal year is a calandar year""",
             states={'confirm': [('readonly', True)]}, domain=[('type', '=', 'cash')]),
         'period_id': fields.many2one('account.period', 'Period', required=True,
+            help="Period is used for creating account moves in selected period",
             states={'confirm':[('readonly', True)]}),
         'balance_start': fields.float('Starting Balance', digits=(16,2),
+            help="must be entered once for the first statement of each journal", 
             states={'confirm':[('readonly',True)]}),
         'balance_end_real': fields.float('Ending Balance', digits=(16,2),
+            help="must be entered and will be compared to calculated result",
             states={'confirm':[('readonly', True)]}),
         'balance_end': fields.function(_end_balance, method=True, string='Balance'),
         'line_ids': fields.one2many('account.bank.statement.line',
@@ -132,13 +144,14 @@ class account_bank_statement(osv.osv):
     }
 
     _defaults = {
-        'name': lambda self, cr, uid, context=None: \
-                self.pool.get('ir.sequence').get(cr, uid, 'account.bank.statement'),
-        'date': lambda *a: time.strftime('%Y-%m-%d'),
+        # FIXME most defaults are return unusable values in daily life
+        #'name': lambda self, cr, uid, context=None: \
+        #        self.pool.get('ir.sequence').get(cr, uid, 'account.bank.statement'),
+        #'date': lambda *a: time.strftime('%Y-%m-%d'),
         'state': lambda *a: 'draft',
         'balance_start': _default_balance_start,
-        'journal_id': _default_journal_id,
-        'period_id': _get_period,
+        #'journal_id': _default_journal_id,
+        #'period_id': _get_period,
     }
 
     def button_confirm(self, cr, uid, ids, context={}):
@@ -195,9 +208,29 @@ class account_bank_statement(osv.osv):
                 amount = res_currency_obj.compute(cr, uid, st.currency.id,
                         company_currency_id, move.amount, context=context,
                         account=acc_cur)
+                # FIXME
+                # need amount later for bank move line
+                amount_move = amount
+                amount_tax = 0.0
+                if move.tax_id:
+                      if move.amount <> move.amount_net + move.amount_tax:
+                          raise osv.except_osv(_('Error !'),
+                              _('VAT and Amount Net do not match Amount in line "%s"') % move.name)
+                      if move.partner_id: 
+                          raise osv.except_osv(_('Error !'),
+                              _('Lines "%s" with VAT must not have partner account ') % move.name)
+                      amount_net = res_currency_obj.compute(cr, uid, st.currency.id,
+                         company_currency_id, move.amount_net, context=context,
+                         account=acc_cur)
+                      amount_tax = amount - amount_net
+                      amount = amount_net
+
                 if move.reconcile_id and move.reconcile_id.line_new_ids:
                     for newline in move.reconcile_id.line_new_ids:
                         amount += newline.amount
+                #   
+                # move line
+                # 
 
                 val = {
                     'name': move.name,
@@ -232,9 +265,36 @@ class account_bank_statement(osv.osv):
                                 move.account_id.currency_id.id, amount, context=context,
                                 account=acc_cur)
                     val['amount_currency'] = amount_cur
+                
+                if amount_tax <> 0.0 and move.tax_id:
+                    val['tax_amount']   = amount_net
+                    val['tax_code_id'] = move.tax_id.base_code_id.id
+              
+                if move.account_analytic_id:
+                    val['analytic_account_id'] = move.account_analytic_id.id
 
                 torec.append(account_move_line_obj.create(cr, uid, val , context=context))
 
+                # VAT Move line                 
+                if amount_tax <> 0.0 and move.tax_id:
+                    account_move_line_obj.create(cr, uid, {
+                    'name': move.name,
+                    'date': move.date,
+                    'ref': move.ref,
+                    'move_id': move_id,
+                    'partner_id': ((move.partner_id) and move.partner_id.id) or False,
+                    'account_id':  move.tax_id.account_collected_id.id,
+                    'credit': ((amount_tax>0) and  amount_tax) or 0.0,
+                    'debit' : ((amount_tax<0) and -amount_tax) or 0.0,
+                    'statement_id': st.id,
+                    'journal_id': st.journal_id.id,
+                    'period_id': st.period_id.id,
+                    'currency_id': st.currency.id,
+                    'tax_amount': amount_tax,
+                    'tax_code_id': move.tax_id.tax_code_id.id,
+                    } , context=context)
+
+
                 if move.reconcile_id and move.reconcile_id.line_new_ids:
                     for newline in move.reconcile_id.line_new_ids:
                         account_move_line_obj.create(cr, uid, {
@@ -254,6 +314,9 @@ class account_bank_statement(osv.osv):
 
                 # Fill the secondary amount/currency
                 # if currency is not the same than the company
+                # Bank Move Line
+                # reset amount to what is was before VAT calculation
+                amount = amount_move
                 amount_currency = False
                 currency_id = False
                 if st.currency.id <> company_currency_id:
@@ -319,7 +382,7 @@ class account_bank_statement(osv.osv):
         self.write(cr, uid, done, {'state':'draft'}, context=context)
         return True
 
-    def onchange_journal_id(self, cursor, user, statement_id, journal_id, context=None):
+    def onchange_journal_id(self, cursor, user, statement_id, journal_id,period_id,name, context=None):
         if not journal_id:
             return {'value': {'currency': False}}
 
@@ -341,7 +404,39 @@ class account_bank_statement(osv.osv):
                     context=context).company_id.currency_id.id
         currency = res_currency_obj.name_get(cursor, user, [currency_id],
                 context=context)[0]
-        return {'value': {'balance_start': balance_start, 'currency': currency}}
+        # FIXME get next Journal number here
+        #'name': lambda self, cr, uid, context=None: \
+        #        self.pool.get('ir.sequence').get(cr, uid, 'account.bank.statement'),
+        # context journal_id, period_id
+        # TODO
+        # check for existing account.sequence.fiscal_year sequence
+        # update next_number
+        if period_id and not name:
+            period_ids = self.pool.get('account.period').search(cursor,user,[('id' ,'=', period_id)])
+            period_obj = self.pool.get('account.period').browse(cursor,user,period_ids)[0]
+            if period_obj:
+                fiscalyear_id = period_obj.fiscalyear_id.id
+            else:
+                raise osv.except_osv(_('Error'), _('No fiscalyear is defined for this period '))
+
+            # FIXME for numbering the bank statements we use the invoice sequence
+            # for numbering the moves the accout journal move sequence shouzld be used
+            sequence_main_id = account_journal_obj.browse(cursor, user, journal_id,
+                context=context).invoice_sequence_id.id
+            if sequence_main_id:
+                sequence_ids = self.pool.get('account.sequence.fiscalyear').search(cursor,user,[('fiscalyear_id','=', fiscalyear_id),('sequence_main_id' ,'=', sequence_main_id)])
+                #sequence_ids = self.pool.get('account.sequence.fiscalyear').search(cursor,user,[('sequence_main_id' ,'=', sequence_main_id)])
+                #sequence_ids = self.pool.get('account.sequence.fiscalyear').search(cursor,user,[('fiscalyear_id','=', fiscalyear_id)])
+            if sequence_ids :
+                sequence_obj = self.pool.get('account.sequence.fiscalyear').browse(cursor,user,sequence_ids)[0]
+                sequence_id = sequence_obj.sequence_id.id
+            else:
+                sequence_id = sequence_main_id
+            
+            name =  self.pool.get('ir.sequence').get_id(cursor,user,  sequence_id )
+
+            
+        return {'value': {'balance_start': balance_start, 'currency': currency, 'name':name}}
 
     def unlink(self, cr, uid, ids, context=None):
         stat = self.read(cr, uid, ids, ['state'])
@@ -353,10 +448,24 @@ class account_bank_statement(osv.osv):
                 raise osv.except_osv(_('Invalid action !'), _('Cannot delete bank statement which are already confirmed !'))
         osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
         return True
+        
+    def onchange_date(self, cursor, user, ids, date):
+        if date:
+            period_ids= self.pool.get('account.period').search(cursor,user,[('date_start','<=',date),('date_stop','>=',date ),('special', '=', False)])
+            if len(period_ids) and len(period_ids) == 1:
+                period_id=period_ids[0]
+            else:
+                raise osv.except_osv(_('Error'), _('No period is or multiple periods are defined for this date '))
+
+            return {'value': {'period_id':period_id}}
+
     
 account_bank_statement()
 
 
+#----------------------------------------------------------------------------
+# Account Bank Statement Reconcile
+#----------------------------------------------------------------------------
 class account_bank_statement_reconcile(osv.osv):
     _name = "account.bank.statement.reconcile"
     _description = "Statement reconcile"
@@ -510,6 +619,9 @@ class account_bank_statement_reconcile(o
     }
 account_bank_statement_reconcile()
 
+#----------------------------------------------------------------------------
+# Account Bank Statement Reconcile Line
+#----------------------------------------------------------------------------
 class account_bank_statement_reconcile_line(osv.osv):
     _name = "account.bank.statement.reconcile.line"
     _description = "Statement reconcile line"
@@ -524,6 +636,9 @@ class account_bank_statement_reconcile_l
     }
 account_bank_statement_reconcile_line()
 
+#----------------------------------------------------------------------------
+# Account Bank Statement Line
+#----------------------------------------------------------------------------
 
 class account_bank_statement_line(osv.osv):
 
@@ -542,22 +657,44 @@ class account_bank_statement_line(osv.os
 
         part = self.pool.get('res.partner').browse(cursor, user, partner_id,
                 context=context)
-        if type == 'supplier':
+ 
+        # quick FIXME check what partner is defined in partner and override input
+        if type == 'partner' :  # trigger runs from partner
+            type = 'general'
+            if not part.supplier and not part.customer :
+                print 'Partner should be customer and/or supplier'  
+                
+            if part.supplier == True and part.customer == True :
+                #type = '' # manual entry necessary FIXME - currently general remains in this case visible - no way to get the select field empty
+                type = 'general'
+                print 'Wizard missing - User has to choose category'  
+            else:
+                if part.supplier == True :
+                    type = 'supplier'
+                if part.customer == True :
+                    type = 'customer'
+       
+        account_id = ''
+        if type == 'supplier': 
             account_id = part.property_account_payable.id
-        else:
+        if type == 'customer': 
             account_id =  part.property_account_receivable.id
-
-        cursor.execute('SELECT sum(debit-credit) \
+     
+        balance = 0.0 
+        if account_id:
+            cursor.execute('SELECT sum(debit-credit) \
                 FROM account_move_line \
                 WHERE (reconcile_id is null) \
                     AND partner_id = %s \
                     AND account_id=%s', (partner_id, account_id))
-        res = cursor.fetchone()
-        balance = res and res[0] or 0.0
+            res = cursor.fetchone()
+            balance = res and res[0] or 0.0
 
-        balance = res_currency_obj.compute(cursor, user, company_currency_id,
+            balance = res_currency_obj.compute(cursor, user, company_currency_id,
                 currency_id, balance, context=context)
-        return {'value': {'amount': balance, 'account_id': account_id}}
+        
+        return {'value': {'amount': balance, 'account_id': account_id,'type': type,
+                 'tax_id':'', 'amount_tax':'', 'amount_net':'' }}
 
     def _reconcile_amount(self, cursor, user, ids, name, args, context=None):
         if not ids:
@@ -582,15 +719,21 @@ class account_bank_statement_line(osv.os
     _name = "account.bank.statement.line"
     _description = "Bank Statement Line"
     _columns = {
-        'name': fields.char('Name', size=64, required=True),
-        'date': fields.date('Date', required=True),
-        'amount': fields.float('Amount'),
+        'name': fields.char('Name', size=64, required=True,
+            help="""automatically adds partner name for general ledger moves"""),
+        'date': fields.date('Date', required=True,
+             help="Keep empty to auto copy date of statement"),
+        'amount': fields.float('Amount', required=True, digits=(16, int(config['price_accuracy'])),
+            help="""positive for cash inflow, negative for cash outflow"""),
         'type': fields.selection([
             ('supplier','Supplier'),
             ('customer','Customer'),
             ('general','General')
-            ], 'Type', required=True),
-        'partner_id': fields.many2one('res.partner', 'Partner'),
+            ], 'Type', required=True,
+            help="""Select 'General' for General Ledger or Customer/Supplier for partners.
+Based on this payables or receivable account defined in partner or properties is selected."""),
+        'partner_id': fields.many2one('res.partner', 'Partner',
+            help="""Customer/Supplier settings will be taken from partner if one and only one box is checked."""),
         'account_id': fields.many2one('account.account','Account',
             required=True),
         'statement_id': fields.many2one('account.bank.statement', 'Statement',
@@ -600,20 +743,88 @@ class account_bank_statement_line(osv.os
         'move_ids': fields.many2many('account.move',
             'account_bank_statement_line_move_rel', 'move_id','statement_id',
             'Moves'),
-        'ref': fields.char('Ref.', size=32),
+        'ref': fields.char('Ref.', size=32,
+            help="""Usually references the move to be reconciled"""),
         'note': fields.text('Notes'),
         'reconcile_amount': fields.function(_reconcile_amount,
             string='Amount reconciled', method=True, type='float'),
+        'tax_id': fields.many2one("account.tax","Tax",
+            help="VAT for this line, only allowed if no partner specified"),
+        'amount_net': fields.float('Amount Net', digits=(16, int(config['price_accuracy'])),
+            help="""Amount Net"""),
+        'amount_tax': fields.float('Amount Tax', digits=(16, int(config['price_accuracy'])),
+            help="""Amount Tax"""),
+        'account_analytic_id':  fields.many2one('account.analytic.account', 'Analytic Account',
+            help="Should only be used for P&amp;L accounts"),
+
+        
     }
     _defaults = {
-        'name': lambda self,cr,uid,context={}: self.pool.get('ir.sequence').get(cr, uid, 'account.bank.statement.line'),
-        'date': lambda *a: time.strftime('%Y-%m-%d'),
+        # FIXME 
+        #'name': lambda self,cr,uid,context={}: self.pool.get('ir.sequence').get(cr, uid, 'account.bank.statement.line'),
+        # FIXME most defaults are return unusable values in daily life
+        #'date': lambda *a: time.strftime('%Y-%m-%d'),
         'type': lambda *a: 'general',
     }
 
-account_bank_statement_line()
+    def onchange_amount(self, cursor, user, ids, date, date_statement,tax_id=False,amount=False):
+        res = {'value' : {'x':'y'}}
+        if not date:
+            date = date_statement
+            res['value']['date'] = date
+
+        if tax_id:
+           tax_obj = self.pool.get('account.tax').browse(cursor, user,tax_id)
+           if tax_obj.type == 'percent' and tax_obj.tax_group == 'vat':
+               amount_net = round(amount / (1 + tax_obj.amount),int(config['price_accuracy']))
+               res['value']['amount_net'] = amount_net
+               res['value']['amount_tax']  = amount - amount_net
 
+        return res
+           
 
+    def onchange_account(self, cursor, user, ids, account_id):
+        result = {}
+        account_obj = self.pool.get('account.account').browse(cursor, user,account_id)
+        tax_id = ''
+        if len(account_obj.tax_ids): 
+            #tax_ids = self.pool.get('account.tax').search(cursor, user, account_obj.tax_ids)
+            #tax_id = tax_ids[0].id
+            cursor.execute( 'select tax_id from account_account_tax_default_rel where account_id = %s limit 1;', (account_id,))
+            res = cursor.fetchone()
+            tax_id = (res and res[0]) or False
+        result = {'value': {
+            'tax_id': tax_id,
+            }
+        }
+        return result 
+        
+    def onchange_tax(self, cursor, user, ids, tax_id, amount ,partner_id): 
+        result = {}
+        amount_net = 0.0
+        amount_tax = 0.0
+        if tax_id:
+            if partner_id:
+                #raise osv.except_osv(_('Error!'),
+                #  _('VAT not allowed for moves lines with partner'))           
+                tax_id = ''
+            else: 
+                tax_obj = self.pool.get('account.tax').browse(cursor, user,tax_id)
+                if tax_obj.type == 'percent' and tax_obj.tax_group == 'vat':
+                    amount_net = round(amount / (1 + tax_obj.amount),int(config['price_accuracy']))
+                    amount_tax = amount - amount_net
+                else:
+                    raise osv.except_osv(_('Error!'),
+                       _('only tax group VAT with percentage supported')) 
+        result = {'value': {
+            'tax_id': tax_id,
+            'amount_net': amount_net,
+            'amount_tax': amount_tax,
+            }
+        }
+        return result
+
+account_bank_statement_line()
 
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
 

References