##############################################################################
#
# Copyright (c) 2004-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
#
# $Id: sale.py 1005 2005-07-25 08:41:42Z nicoe $
#
# 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 contract 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 osv import fields, osv
import ir

class partner_wh_rebate(osv.osv):
	_name = "res.partner"
	_inherit = "res.partner"
	_columns = {
		'rebate': fields.float('Rebate (%)', digits=(5, 2)),
	}
partner_wh_rebate()

class sale_order_rebate(osv.osv):
	_name = "sale.order"
	_inherit = "sale.order"

	def _amount_wo_rebate(self, cr, uid, ids, field_name, arg, context):
		return super(sale_order_rebate, self)._amount_untaxed(cr, uid, ids, field_name, arg, context)

	def _amount_rebate(self, cr, uid, ids, field_name, arg, context):
		wo_rebate = self._amount_wo_rebate(cr, uid, ids, field_name, arg, context) 
		orders = self.read(cr, uid, ids, ['rebate_percent'], context)
		rebates = dict([(o['id'], o['rebate_percent']) for o in orders])
		res = {}
		for id in ids:
			res[id] = wo_rebate.get(id, 0.0) * (rebates.get(id, 0.0) / 100.0)
		return res

	def _amount_untaxed(self, cr, uid, ids, field_name, arg, context):
		wo_rebate = self._amount_wo_rebate(cr, uid, ids, field_name, arg, context) 
		rebate = self._amount_rebate(cr, uid, ids, field_name, arg, context)
		res = {}
		for id in ids:
			res[id] = wo_rebate.get(id, 0.0) - rebate.get(id, 0.0)
		return res
		
	def _amount_tax(self, cr, uid, ids, field_name, arg, context):
		res = {}
		for order in self.browse(cr, uid, ids):
			val = 0.0
			for line in order.order_line:
				for tax in line.tax_id:
					for c in self.pool.get('account.tax').compute(cr, uid, [tax.id], line.price_unit, line.product_uom_qty, order.partner_invoice_id.id):
						val += c['amount'] * (100.0 - order.rebate_percent) / 100.0
			res[order.id] = val
		return res

	_columns = {
		'rebate_percent': fields.float('Rebate (%)', digits=(5, 2), readonly=True, states={'draft':[('readonly',False)]}),
#		'rebate_account': fields.many2one('account.account', 'Rebate account', required=True, readonly=True, states={'draft':[('readonly',False)]}),
		'amount_wo_rebate': fields.function(_amount_wo_rebate, method=True, string='Intermediate sum'),
		'amount_rebate': fields.function(_amount_rebate, method=True, string='Rebate'),
		'amount_untaxed': fields.function(_amount_untaxed, method=True, string='Untaxed Amount'),
		'amount_tax': fields.function(_amount_tax, method=True, string='Taxes'),
	}
	_defaults = {
		'rebate_percent': lambda *a: 0.0,
	}

	#
	# Why not using super().onchange_partner_id ?
	#
	def onchange_partner_id(self, cr, uid, ids, partner_id):
		if not partner_id:
			return {'value': {'partner_invoice_id': False, 'partner_shipping_id': False, 'partner_order_id': False}}
		partner = self.pool.get('res.partner').browse(cr, uid, partner_id)
		addr = self.pool.get('res.partner').address_get(cr, uid, [partner_id], ['delivery', 'invoice', 'contact'])
		pricelist = partner.property_product_pricelist[0]
		return {
			'value': {
				'rebate_percent': partner.rebate or 0.0, 
				'partner_invoice_id': addr['invoice'],
				'partner_order_id': addr['contact'],
				'partner_shipping_id': addr['delivery'],
				'pricelist_id': pricelist
			}
		}

	def action_invoice_create(self, cr, uid, ids, grouped=False, states=['confirmed','done']):
		assert len(ids)==1, "Can only invoice one sale order at a time"
		invoice_id = super(sale_order_rebate, self).action_invoice_create(cr, uid, ids, grouped, states)
		if invoice_id:
			order = self.browse(cr, uid, ids[0])
			inv_obj = self.pool.get('account.invoice')
			inv_obj.write(cr, uid, [invoice_id], {'rebate_percent': order.rebate_percent})
			inv_obj.button_compute(cr, uid, [invoice_id])
		return invoice_id
sale_order_rebate()

class account_invoice_wh_rebate(osv.osv):
	_name = "account.invoice"
	_inherit = "account.invoice"

	def _amount_wo_rebate(self, cr, uid, ids, field_name, arg, context):
		return super(account_invoice_wh_rebate, self)._amount_untaxed(cr, uid, ids, field_name, arg, context)

	def _amount_untaxed(self, cr, uid, ids, field_name, arg, context):
		un_taxed = super(account_invoice_wh_rebate, self)._amount_untaxed(cr, uid, ids, field_name, arg, context)
		res = {}
		for invoice in self.browse(cr, uid, ids):
			res[invoice.id] = un_taxed[invoice.id] - invoice.rebate_amount
		return res

	_columns = {
		'amount_wo_rebate': fields.function(_amount_wo_rebate, method=True, string='Intermediate sum'),
		'amount_untaxed': fields.function(_amount_untaxed, method=True, string='Untaxed Amount'),
		'rebate_percent': fields.float('Rebate (%)', digits=(5, 2), readonly=True),
		'rebate_amount': fields.float('Rebate amount', digits=(14, 2), readonly=True)
	}
account_invoice_wh_rebate()

class account_invoice_line_wh_rebate(osv.osv):
	_name = "account.invoice.line"
	_inherit = "account.invoice.line"

	def move_line_get(self, cr, uid, invoice_id):
		invoice = self.pool.get('account.invoice').browse(cr, uid, invoice_id)
		res = []
		tax_grouped = {}
		tax_obj = self.pool.get('account.tax')
#TODO: rewrite using browse instead of the manual SQL queries
		cr.execute('SELECT * FROM account_invoice_line WHERE invoice_id=%d', (invoice_id,))
		lines = cr.dictfetchall()
		rebate_percent = invoice.rebate_percent
		rebate_amount = 0.0
		for line in lines:
			price_unit = line['price_unit'] * (100.0 - rebate_percent) / 100.0
			res.append({'type':'src', 'name':line['name'], 'price_unit':price_unit, 'quantity':line['quantity'], 'price':round(line['quantity']*price_unit, 2), 'account_id':line['account_id']})
			cr.execute('SELECT tax_id FROM account_invoice_line_tax WHERE invoice_line_id=%d', (line['id'],))
			rebate_amount += (line['price_unit'] * rebate_percent / 100.0) * line['quantity']
			for (tax_id,) in cr.fetchall():
				# even though we pass only one tax id at a time to compute, it can return several results
				# in case a tax has a parent tax
				sequence = tax_obj.read(cr, uid, [tax_id], ['sequence'])[0]['sequence']
				for tax in tax_obj.compute(cr, uid, [tax_id], price_unit, line['quantity'], invoice.address_invoice_id.id):
					tax['sequence'] = sequence
					if invoice.type in ('out_invoice','in_refund'):
						tax['account_id'] = tax['account_collected_id']
					else:
						tax['account_id'] = tax['account_paid_id']
					key = tax['account_id']
					if not key in tax_grouped:
						tax_grouped[key] = tax
					else:
						tax_grouped[key]['amount'] += tax['amount']
		# delete automatic tax lines for this invoice
		cr.execute("DELETE FROM account_invoice_tax WHERE NOT manual AND invoice_id=%d", (invoice_id,))
		
		# (re)create them
		ait = self.pool.get('account.invoice.tax')
		for t in tax_grouped.values():
			ait.create(cr, uid, {'invoice_id':invoice_id, 'name':t['name'], 'account_id':t['account_id'], 'amount':t['amount'], 'manual':False, 'sequence':t['sequence']})

		# update rebate amount for this invoice
		self.pool.get('account.invoice').write(cr, uid, [invoice_id], {'rebate_amount': rebate_amount})
		return res
account_invoice_line_wh_rebate()

