Server IP : 127.0.0.2 / Your IP : 3.15.195.46 Web Server : Apache/2.4.18 (Ubuntu) System : User : www-data ( ) PHP Version : 7.0.33-0ubuntu0.16.04.16 Disable Function : disk_free_space,disk_total_space,diskfreespace,dl,exec,fpaththru,getmyuid,getmypid,highlight_file,ignore_user_abord,leak,listen,link,opcache_get_configuration,opcache_get_status,passthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,php_uname,phpinfo,posix_ctermid,posix_getcwd,posix_getegid,posix_geteuid,posix_getgid,posix_getgrgid,posix_getgrnam,posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp,posix_getpid,posix,_getppid,posix_getpwnam,posix_getpwuid,posix_getrlimit,posix_getsid,posix_getuid,posix_isatty,posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid,posix_setpgid,posix_setsid,posix_setuid,posix_times,posix_ttyname,posix_uname,pclose,popen,proc_open,proc_close,proc_get_status,proc_nice,proc_terminate,shell_exec,source,show_source,system,virtual MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /opt/odoo/addons/sale/wizard/ |
Upload File : |
# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. import time from odoo import api, fields, models, _ import odoo.addons.decimal_precision as dp from odoo.exceptions import UserError class SaleAdvancePaymentInv(models.TransientModel): _name = "sale.advance.payment.inv" _description = "Sales Advance Payment Invoice" @api.model def _count(self): return len(self._context.get('active_ids', [])) @api.model def _get_advance_payment_method(self): if self._count() == 1: sale_obj = self.env['sale.order'] order = sale_obj.browse(self._context.get('active_ids'))[0] if all([line.product_id.invoice_policy == 'order' for line in order.order_line]) or order.invoice_count: return 'all' return 'delivered' @api.model def _default_product_id(self): product_id = self.env['ir.values'].get_default('sale.config.settings', 'deposit_product_id_setting') return self.env['product.product'].browse(product_id) @api.model def _default_deposit_account_id(self): return self._default_product_id().property_account_income_id @api.model def _default_deposit_taxes_id(self): return self._default_product_id().taxes_id advance_payment_method = fields.Selection([ ('delivered', 'Invoiceable lines'), ('all', 'Invoiceable lines (deduct down payments)'), ('percentage', 'Down payment (percentage)'), ('fixed', 'Down payment (fixed amount)') ], string='What do you want to invoice?', default=_get_advance_payment_method, required=True) product_id = fields.Many2one('product.product', string='Down Payment Product', domain=[('type', '=', 'service')], default=_default_product_id) count = fields.Integer(default=_count, string='# of Orders') amount = fields.Float('Down Payment Amount', digits=dp.get_precision('Account'), help="The amount to be invoiced in advance, taxes excluded.") deposit_account_id = fields.Many2one("account.account", string="Income Account", domain=[('deprecated', '=', False)], help="Account used for deposits", default=_default_deposit_account_id) deposit_taxes_id = fields.Many2many("account.tax", string="Customer Taxes", help="Taxes used for deposits", default=_default_deposit_taxes_id) @api.onchange('advance_payment_method') def onchange_advance_payment_method(self): if self.advance_payment_method == 'percentage': return {'value': {'amount': 0}} return {} @api.multi def _create_invoice(self, order, so_line, amount): inv_obj = self.env['account.invoice'] ir_property_obj = self.env['ir.property'] account_id = False if self.product_id.id: account_id = self.product_id.property_account_income_id.id if not account_id: inc_acc = ir_property_obj.get('property_account_income_categ_id', 'product.category') account_id = order.fiscal_position_id.map_account(inc_acc).id if inc_acc else False if not account_id: raise UserError( _('There is no income account defined for this product: "%s". You may have to install a chart of account from Accounting app, settings menu.') % (self.product_id.name,)) if self.amount <= 0.00: raise UserError(_('The value of the down payment amount must be positive.')) if self.advance_payment_method == 'percentage': amount = order.amount_untaxed * self.amount / 100 name = _("Down payment of %s%%") % (self.amount,) else: amount = self.amount name = _('Down Payment') taxes = self.product_id.taxes_id.filtered(lambda r: not order.company_id or r.company_id == order.company_id) if order.fiscal_position_id and taxes: tax_ids = order.fiscal_position_id.map_tax(taxes).ids else: tax_ids = taxes.ids invoice = inv_obj.create({ 'name': order.client_order_ref or order.name, 'origin': order.name, 'type': 'out_invoice', 'reference': False, 'account_id': order.partner_id.property_account_receivable_id.id, 'partner_id': order.partner_invoice_id.id, 'partner_shipping_id': order.partner_shipping_id.id, 'invoice_line_ids': [(0, 0, { 'name': name, 'origin': order.name, 'account_id': account_id, 'price_unit': amount, 'quantity': 1.0, 'discount': 0.0, 'uom_id': self.product_id.uom_id.id, 'product_id': self.product_id.id, 'sale_line_ids': [(6, 0, [so_line.id])], 'invoice_line_tax_ids': [(6, 0, tax_ids)], 'account_analytic_id': order.project_id.id or False, })], 'currency_id': order.pricelist_id.currency_id.id, 'payment_term_id': order.payment_term_id.id, 'fiscal_position_id': order.fiscal_position_id.id or order.partner_id.property_account_position_id.id, 'team_id': order.team_id.id, 'user_id': order.user_id.id, 'comment': order.note, }) invoice.compute_taxes() invoice.message_post_with_view('mail.message_origin_link', values={'self': invoice, 'origin': order}, subtype_id=self.env.ref('mail.mt_note').id) return invoice @api.multi def create_invoices(self): sale_orders = self.env['sale.order'].browse(self._context.get('active_ids', [])) if self.advance_payment_method == 'delivered': sale_orders.action_invoice_create() elif self.advance_payment_method == 'all': sale_orders.action_invoice_create(final=True) else: # Create deposit product if necessary if not self.product_id: vals = self._prepare_deposit_product() self.product_id = self.env['product.product'].create(vals) self.env['ir.values'].sudo().set_default('sale.config.settings', 'deposit_product_id_setting', self.product_id.id) sale_line_obj = self.env['sale.order.line'] for order in sale_orders: if self.advance_payment_method == 'percentage': amount = order.amount_untaxed * self.amount / 100 else: amount = self.amount if self.product_id.invoice_policy != 'order': raise UserError(_('The product used to invoice a down payment should have an invoice policy set to "Ordered quantities". Please update your deposit product to be able to create a deposit invoice.')) if self.product_id.type != 'service': raise UserError(_("The product used to invoice a down payment should be of type 'Service'. Please use another product or update this product.")) taxes = self.product_id.taxes_id.filtered(lambda r: not order.company_id or r.company_id == order.company_id) if order.fiscal_position_id and taxes: tax_ids = order.fiscal_position_id.map_tax(taxes).ids else: tax_ids = taxes.ids so_line = sale_line_obj.create({ 'name': _('Advance: %s') % (time.strftime('%m %Y'),), 'price_unit': amount, 'product_uom_qty': 0.0, 'order_id': order.id, 'discount': 0.0, 'product_uom': self.product_id.uom_id.id, 'product_id': self.product_id.id, 'tax_id': [(6, 0, tax_ids)], }) self._create_invoice(order, so_line, amount) if self._context.get('open_invoices', False): return sale_orders.action_view_invoice() return {'type': 'ir.actions.act_window_close'} def _prepare_deposit_product(self): return { 'name': 'Down payment', 'type': 'service', 'invoice_policy': 'order', 'property_account_income_id': self.deposit_account_id.id, 'taxes_id': [(6, 0, self.deposit_taxes_id.ids)], }