# -*- coding: utf-8 -*-

from openerp import models, fields, api, _
from openerp.exceptions import UserError, ValidationError, Warning

class SalesCommission(models.Model):
    _name = "sales.commission"
    _deacription = "Sales Commission"
    _order = 'id desc'
    _rec_name = 'name'
#     _inherit = ['mail.thread', 'ir.needaction_mixin']
    _inherit = ['mail.thread', 'mail.activity.mixin', 'portal.mixin'] #odoo11

    @api.multi
    @api.depends('sales_commission_line', 'sales_commission_line.state')
    def _get_amount_total(self):
        for rec in self:
            total_amount = []
            for line in rec.sales_commission_line:
                if line.state not in ['cancel', 'exception']:
                    total_amount.append(line.amount_company_currency)#multi currency supported
            rec.amount = sum(total_amount)

    @api.model
    def create(self, vals):
        vals['name'] = self.env['ir.sequence'].next_by_code('sales.commission')
        return super(SalesCommission, self).create(vals)
    
#    @api.multi
#    def unlink(self):
#        for rec in self:
#            if rec:
#                raise UserError(_('You can not delete Sales Commission.'))

    @api.multi
    @api.depends('invoice_id','invoice_id.state')
    def _is_paid_invoice(self):
        for rec in self:
            if rec.invoice_id.state == 'paid':
                rec.is_paid = True
                rec.state = 'paid'

    name = fields.Char(
        string="Name",
        readonly=True,
    )
    state = fields.Selection([
        ('draft', 'Draft'),
        ('invoice', 'Invoiced'),
        ('paid', 'Paid'),
        ('cancel', 'Cancelled')],
        default='draft',
        track_visibility='onchange',
        copy=False, string="Status"
    )
    start_date = fields.Datetime(
        string='Start Date',
        readonly=True, states={'draft': [('readonly', False)]},
    )
    end_date = fields.Datetime(
        string='End Date',
        readonly=True, states={'draft': [('readonly', False)]},
    )
    commission_user_id = fields.Many2one(
        'res.users',
        string='Sales Member',
        required=True,
        readonly=True, states={'draft': [('readonly', False)]},
    )
    sales_commission_line = fields.One2many(
        'sales.commission.line',
        'sales_commission_id',
        string="Commission Line",
        readonly=True, states={'draft': [('readonly', False)]},
    )
    notes = fields.Text(string="Internal Notes")
    company_id = fields.Many2one(
        'res.company', 
        default=lambda self: self.env.user.company_id, 
        string='Company', 
        readonly=True
    )
    product_id = fields.Many2one(
        'product.product',
        domain=[('is_commission_product','=',True)],
        string='Commision Product For Invoice',
        readonly=True, states={'draft': [('readonly', False)]},
    )
    amount = fields.Float(
        string='Total Commision Amount (Company Currency)',
        compute="_get_amount_total",
        store=True,
        readonly=True, states={'draft': [('readonly', False)]},
    )
    invoice_id = fields.Many2one(
        'account.invoice',
        string='Commission Invoice',
        readonly=True, states={'draft': [('readonly', False)]},
    )
    is_paid = fields.Boolean(
        string="Is Commission Paid",
        compute="_is_paid_invoice",
        store=True,
        readonly=True, states={'draft': [('readonly', False)]},
    )
    currency_id = fields.Many2one(
        'res.currency', 
        related='company_id.currency_id',
        string='Currency', 
        readonly=True, states={'draft': [('readonly', False)]}
    )
    
    @api.multi
    def _prepare_invoice_line(self, invoice_id):
        """
        Prepare the dict of values to create the new invoice line for a sales order line.
        :param qty: float quantity to invoice
        """
        res = {}
        for rec in self:
            product = rec.product_id
            account = product.property_account_expense_id or product.categ_id.property_account_expense_categ_id
            if not account:
                raise UserError(_('Please define expense account for this product: "%s" (id:%d) - or for its category: "%s".') % \
                            (product.name, product.id, product.categ_id.name))
            fpos = invoice_id.partner_id.property_account_position_id
            if fpos:
                account = fpos.map_account(account)
            #for title service
            res = {
                'name': product.name,
                'origin': invoice_id.origin,
                'account_id': account.id,
                'price_unit': rec.amount,#To do
                'quantity': 1,
                'uom_id': product.uom_id.id,
                'product_id': product.id or False,
            }
        return res

    @api.multi
    def invoice_line_create(self, invoice_id):
        precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
        for rec in self:
            vals = rec._prepare_invoice_line(invoice_id=invoice_id)
            vals.update({'invoice_id': invoice_id.id})
            self.env['account.invoice.line'].create(vals)

    @api.multi
    def _prepare_invoice(self):
        """
        Prepare the dict of values to create the new invoice . This method may be
        overridden to implement custom invoice generation (making sure to call super() to establish
        a clean extension chain).
        """
        self.ensure_one()
        
        #find Applicant as a invoice related
        partner = self.commission_user_id.partner_id
        #applicant = self.applicant_ids.search([('applicant_based_on_invoice','=',True)],limit=1)
        if not partner.property_product_pricelist:
            raise Warning(_('Please set pricelist.'))

        domain = [
            ('type', '=', 'purchase'),
            ('company_id', '=', self.company_id.id),]
        journal_id = self.env['account.journal'].search(domain, limit=1)
        if not journal_id:
            raise UserError(_('Please configure an accounting sale journal for this company.'))
        
        invoice_vals = {
            'name': self.name or '',
            'origin': self.name,
            'type': 'in_invoice',
            'account_id': partner.property_account_receivable_id.id,
            'partner_id': partner.id,
            'journal_id': journal_id.id,
            'currency_id': partner.property_product_pricelist.currency_id.id,
            'comment': partner.name,
            'payment_term_id': partner.property_payment_term_id.id,
            'fiscal_position_id': partner.property_account_position_id.id,
            'company_id': self.company_id.id,
            'user_id': self.commission_user_id and self.commission_user_id.id,
            'sale_commission_id': self.id,
        }
        return invoice_vals
        
    @api.multi
    def action_create_invoice(self):
        inv_obj = self.env['account.invoice']
        inv_line_obj = self.env['account.invoice.line']
        for rec in self:
            #invoice create
            inv_data = rec._prepare_invoice()
            invoice = inv_obj.create(inv_data)
#            #invoice line create
            rec.invoice_line_create(invoice)
            rec.invoice_id = invoice.id
            rec.state = 'invoice'
            for line in rec.sales_commission_line:
                if line.state not in ['cancel', 'exception']:
                    line.state = 'invoice'
            
    @api.multi
    def action_cancel(self):
        for rec in self:
            rec.state = 'cancel'

    @api.multi
    def action_draft(self):
        for rec in self:
            rec.state = 'draft'

class SalesCommissionLine(models.Model):
    _name = "sales.commission.line"
    _deacription = "Sales Commission"
    _order = 'id desc'
    _rec_name = 'sales_commission_id'
#     _inherit = ['mail.thread', 'ir.needaction_mixin']
    _inherit = ['mail.thread', 'mail.activity.mixin', 'portal.mixin'] #odoo11
    
    @api.model
    def create(self, vals):
        vals['name'] = self.env['ir.sequence'].next_by_code('sales.commission.line')
        return super(SalesCommissionLine, self).create(vals)
    
#    @api.multi
#    def unlink(self):
#        for rec in self:
#            if rec:
#                raise UserError(_('You can not delete Sales Commission Line'))
            
    @api.multi
    @api.depends('amount','currency_id', 'src_order_id', 'src_invoice_id', 'src_payment_id')
    def _compute_amount_company_currency(self):
        for rec in self:
            if rec.src_order_id:
                rec.amount_company_currency = rec.src_order_id.currency_id.compute(rec.amount, rec.currency_id)
            if rec.src_invoice_id:
                rec.amount_company_currency = rec.src_invoice_id.currency_id.compute(rec.amount, rec.currency_id)
            if rec.src_payment_id:
                rec.amount_company_currency = rec.src_payment_id.currency_id.compute(rec.amount, rec.currency_id)
    @api.multi
    @api.depends('amount','currency_id', 'src_order_id', 'src_invoice_id', 'src_payment_id')
    def _compute_source_currency(self):
        for rec in self:
            if rec.src_order_id:
                rec.source_currency = rec.src_order_id.currency_id.id
            if rec.src_invoice_id:
                rec.source_currency = rec.src_invoice_id.currency_id.id
            if rec.src_payment_id:
                rec.source_currency = rec.src_payment_id.currency_id.id
    
    sales_commission_id = fields.Many2one(
        'sales.commission',
        string="Sales Commission",
    )
    name = fields.Char(
        string="Name",
        readonly=True,
    )
    sales_team_id = fields.Many2one(
        'crm.team',
        string='Sales Team',
        reqired=True
    )
    commission_user_id = fields.Many2one(
        'res.users',
        string='Sales Member',
        related='sales_commission_id.commission_user_id',
    )
    amount = fields.Float(
        string='Amount'
    )
    source_currency = fields.Many2one(
        'res.currency', 
        string='Source Currency',
        compute='_compute_source_currency',
        store=True
    )
    company_id = fields.Many2one(
        'res.company', 
        default=lambda self: self.env.user.company_id, 
        string='Company', 
        readonly=True
    )
    origin = fields.Char(string='Source Document', copy=False)
    notes = fields.Text(string="Internal Notes")

    state = fields.Selection([
        ('draft', 'Draft'),
        ('invoice', 'Invoiced'),
        ('paid', 'Paid'),
        ('exception','Exception'),
        ('cancel', 'Cancelled'),
        ],
        default='draft',
        track_visibility='onchange',
        copy=False, string="Status"
    )
    product_id = fields.Many2one(
        'product.product',
        domain=[('is_commission_product','=',True)],
        string='Product'
    )
    type = fields.Selection(
        [('sales_person', 'Sales Person'),
        ('sales_manager', 'Sales Manager')],
        copy=False, 
        string="User Type",
    )
    invoice_id = fields.Many2one(
        'account.invoice',
        string='Account Invoice'
    )
    date = fields.Datetime(
        string='Commission Date',
    )
    amount_company_currency = fields.Float(
        string='Amount in Company Currency',
        compute='_compute_amount_company_currency',
        store=True
    )
    currency_id = fields.Many2one(
        'res.currency', 
        default=lambda self: self.env.user.company_id.currency_id.id,
        string='Currency', 
    )
    src_invoice_id = fields.Many2one(
        'account.invoice',
        string='Source Invoice'
    )
    src_order_id = fields.Many2one(
        'sale.order',
        string='Source Sale Order'
    )
    src_payment_id = fields.Many2one(
        'account.payment',
        string='Source Payment'
    )
    is_paid = fields.Boolean(
        string="Is Commision Line Paid",
        related="sales_commission_id.is_paid",
        store=True,
    )

#    @api.multi
#    def _prepare_invoice_line(self, invoice_id):
#        """
#        Prepare the dict of values to create the new invoice line for a sales order line.
#        :param qty: float quantity to invoice
#        """
#        res = {}
#        for rec in self:
#            product = rec.product_id
#            account = product.property_account_income_id or product.categ_id.property_account_income_categ_id
#            if not account:
#                raise UserError(_('Please define income account for this product: "%s" (id:%d) - or for its category: "%s".') % \
#                            (product.name, product.id, product.categ_id.name))
#            fpos = invoice_id.partner_id.property_account_position_id
#            if fpos:
#                account = fpos.map_account(account)
#            #for title service
#            res = {
#                'name': invoice_id.origin,
#                'origin': invoice_id.origin,
#                'account_id': account.id,
#                'price_unit': rec.amount,#To do
#                'quantity': 1,
#                'uom_id': product.uom_id.id,
#                'product_id': product.id or False,
#            }
#        return res

#    @api.multi
#    def invoice_line_create(self, invoice_id):
#        precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
#        for rec in self:
#            vals = rec._prepare_invoice_line(invoice_id=invoice_id)
#            vals.update({'invoice_id': invoice_id.id})
#            self.env['account.invoice.line'].create(vals)

#    @api.multi
#    def _prepare_invoice(self):
#        """
#        Prepare the dict of values to create the new invoice . This method may be
#        overridden to implement custom invoice generation (making sure to call super() to establish
#        a clean extension chain).
#        """
#        self.ensure_one()
#        
#        #find Applicant as a invoice related
#        partner = self.commission_user_id.partner_id
#        #applicant = self.applicant_ids.search([('applicant_based_on_invoice','=',True)],limit=1)
#        if not partner.property_product_pricelist:
#            raise Warning(_('Please set pricelist.'))

#        domain = [
#            ('type', '=', 'sale'),
#            ('company_id', '=', self.company_id.id),]
#        journal_id = self.env['account.journal'].search(domain, limit=1)
#        if not journal_id:
#            raise UserError(_('Please configure an accounting sale journal for this company.'))
#        
#        invoice_vals = {
#            'name': self.name or '',
#            'origin': self.name,
#            'type': 'in_invoice',
#            'account_id': partner.property_account_receivable_id.id,
#            'partner_id': partner.id,
#            'journal_id': journal_id.id,
#            'currency_id': partner.property_product_pricelist.currency_id.id,
#            'comment': partner.name,
#            'payment_term_id': partner.property_payment_term_id.id,
#            'fiscal_position_id': partner.property_account_position_id.id,
#            'company_id': self.company_id.id,
#            'user_id': self.commission_user_id and self.commission_user_id.id,
#            'sale_commission_id': self.id,
#        }
#        return invoice_vals

#    @api.multi
#    def action_create_invoice(self):
#        inv_obj = self.env['account.invoice']
#        inv_line_obj = self.env['account.invoice.line']
#        for rec in self:
#            #invoice create
#            inv_data = rec._prepare_invoice()
#            invoice = inv_obj.create(inv_data)
##            #invoice line create
#            rec.invoice_line_create(invoice)
#            rec.invoice_id = invoice.id
#            rec.state = 'invoice'

    @api.multi
    def action_cancel(self):
        self.state = 'cancel'
    

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
