Merge with addons/trunk revno 8168.
[odoo/odoo.git] / addons / account / partner.py
index 67f20b3..b5e0a95 100644 (file)
@@ -20,8 +20,8 @@
 ##############################################################################
 
 from operator import itemgetter
-
 from osv import fields, osv
+import time
 
 class account_fiscal_position(osv.osv):
     _name = 'account.fiscal.position'
@@ -44,17 +44,17 @@ class account_fiscal_position(osv.osv):
             return []
         if not fposition_id:
             return map(lambda x: x.id, taxes)
-        result = []
+        result = set()
         for t in taxes:
             ok = False
             for tax in fposition_id.tax_ids:
                 if tax.tax_src_id.id == t.id:
                     if tax.tax_dest_id:
-                        result.append(tax.tax_dest_id.id)
+                        result.add(tax.tax_dest_id.id)
                     ok=True
             if not ok:
-                result.append(t.id)
-        return result
+                result.add(t.id)
+        return list(result)
 
     def map_account(self, cr, uid, fposition_id, account_id, context=None):
         if not fposition_id:
@@ -77,6 +77,12 @@ class account_fiscal_position_tax(osv.osv):
         'tax_dest_id': fields.many2one('account.tax', 'Replacement Tax')
     }
 
+    _sql_constraints = [
+        ('tax_src_dest_uniq',
+         'unique (position_id,tax_src_id,tax_dest_id)',
+         'A tax fiscal position could be defined only once time on same taxes.')
+    ]
+
 account_fiscal_position_tax()
 
 class account_fiscal_position_account(osv.osv):
@@ -89,6 +95,12 @@ class account_fiscal_position_account(osv.osv):
         'account_dest_id': fields.many2one('account.account', 'Account Destination', domain=[('type','<>','view')], required=True)
     }
 
+    _sql_constraints = [
+        ('account_src_dest_uniq',
+         'unique (position_id,account_src_id,account_dest_id)',
+         'An account fiscal position could be defined only once time on same accounts.')
+    ]
+
 account_fiscal_position_account()
 
 class res_partner(osv.osv):
@@ -145,6 +157,29 @@ class res_partner(osv.osv):
     def _debit_search(self, cr, uid, obj, name, args, context=None):
         return self._asset_difference_search(cr, uid, obj, name, 'payable', args, context=context)
 
+    def has_something_to_reconcile(self, cr, uid, partner_id, context=None):
+        '''
+        at least a debit, a credit and a line older than the last reconciliation date of the partner
+        '''
+        cr.execute('''
+            SELECT l.partner_id, SUM(l.debit) AS debit, SUM(l.credit) AS credit
+            FROM account_move_line l
+            RIGHT JOIN account_account a ON (a.id = l.account_id)
+            RIGHT JOIN res_partner p ON (l.partner_id = p.id)
+            WHERE a.reconcile IS TRUE
+            AND p.id = %s
+            AND l.reconcile_id IS NULL
+            AND (p.last_reconciliation_date IS NULL OR l.date > p.last_reconciliation_date)
+            AND l.state <> 'draft'
+            GROUP BY l.partner_id''', (partner_id,))
+        res = cr.dictfetchone()
+        if res:
+            return bool(res['debit'] and res['credit'])
+        return False
+
+    def mark_as_reconciled(self, cr, uid, ids, context=None):
+        return self.write(cr, uid, ids, {'last_reconciliation_date': time.strftime('%Y-%m-%d %H:%M:%S')}, context=context)
+
     _columns = {
         'credit': fields.function(_credit_debit_get,
             fnct_search=_credit_search, string='Total Receivable', multi='dc', help="Total amount this customer owes you."),
@@ -174,7 +209,7 @@ class res_partner(osv.osv):
             relation='account.fiscal.position',
             string="Fiscal Position",
             view_load=True,
-            help="The fiscal position will determine taxes and the accounts used for the partner.",
+            help="The fiscal position will determine taxes and accounts used for the partner.",
         ),
         'property_payment_term': fields.property(
             'account.payment.term',
@@ -192,7 +227,7 @@ class res_partner(osv.osv):
              help="This payment term will be used instead of the default one for purchase orders and supplier invoices"),
         'ref_companies': fields.one2many('res.company', 'partner_id',
             'Companies that refers to partner'),
-        'last_reconciliation_date': fields.datetime('Latest Reconciliation Date', help='Date on which the partner accounting entries were reconciled last time')
+        'last_reconciliation_date': fields.datetime('Latest Reconciliation Date', help='Date on which the partner accounting entries were fully reconciled last time. It differs from the date of the last reconciliation made for this partner, as here we depict the fact that nothing more was to be reconciled at this date. This can be achieved in 2 ways: either the last debit/credit entry was reconciled, either the user pressed the button "Fully Reconciled" in the manual reconciliation process')
     }
 
 res_partner()