From eac6c1a14712be9a316db07b46e35dbee492ada5 Mon Sep 17 00:00:00 2001 From: Avanzosc Date: Tue, 30 Jul 2019 09:05:47 +0200 Subject: [PATCH] =?UTF-8?q?[ADD]=20sale=5Forder=5Frental:=20This=20module?= =?UTF-8?q?=20put=20the=20start=20date,=20end=20date=20and=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sale_order_rental/README.rst | 28 ++++ sale_order_rental/__init__.py | 2 + sale_order_rental/__manifest__.py | 21 +++ sale_order_rental/i18n/es.po | 96 ++++++++++++ sale_order_rental/i18n/sale_order_rental.pot | 96 ++++++++++++ sale_order_rental/models/__init__.py | 3 + sale_order_rental/models/account_invoice.py | 103 +++++++++++++ sale_order_rental/models/sale_order.py | 143 ++++++++++++++++++ sale_order_rental/models/stock.py | 26 ++++ .../security/ir.model.access.csv | 3 + sale_order_rental/static/img/enviado.png | Bin 0 -> 14165 bytes .../views/account_invoice_view.xml | 19 +++ sale_order_rental/views/sale_order_view.xml | 41 +++++ .../views/stock_picking_view.xml | 30 ++++ sale_order_rental/wizards/__init__.py | 1 + .../wizards/stock_picking_return.py | 17 +++ 16 files changed, 629 insertions(+) create mode 100644 sale_order_rental/README.rst create mode 100644 sale_order_rental/__init__.py create mode 100644 sale_order_rental/__manifest__.py create mode 100644 sale_order_rental/i18n/es.po create mode 100644 sale_order_rental/i18n/sale_order_rental.pot create mode 100644 sale_order_rental/models/__init__.py create mode 100644 sale_order_rental/models/account_invoice.py create mode 100644 sale_order_rental/models/sale_order.py create mode 100644 sale_order_rental/models/stock.py create mode 100644 sale_order_rental/security/ir.model.access.csv create mode 100644 sale_order_rental/static/img/enviado.png create mode 100755 sale_order_rental/views/account_invoice_view.xml create mode 100755 sale_order_rental/views/sale_order_view.xml create mode 100755 sale_order_rental/views/stock_picking_view.xml create mode 100644 sale_order_rental/wizards/__init__.py create mode 100644 sale_order_rental/wizards/stock_picking_return.py diff --git a/sale_order_rental/README.rst b/sale_order_rental/README.rst new file mode 100644 index 00000000..e47289c8 --- /dev/null +++ b/sale_order_rental/README.rst @@ -0,0 +1,28 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +================= +Sale order rental +================= + +* This module put the start date, end date and rental days in sale orders, delivery notes and invoices. + + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smash it by providing detailed and welcomed feedback. + +Credits +======= + +Contributors +------------ +* Ana Juaristi +* Oihana Larrañaga + +Do not contact contributors directly about support or help with technical issues. diff --git a/sale_order_rental/__init__.py b/sale_order_rental/__init__.py new file mode 100644 index 00000000..aee8895e --- /dev/null +++ b/sale_order_rental/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizards diff --git a/sale_order_rental/__manifest__.py b/sale_order_rental/__manifest__.py new file mode 100644 index 00000000..1bf63436 --- /dev/null +++ b/sale_order_rental/__manifest__.py @@ -0,0 +1,21 @@ +# Copyright 2019 Oihana Larrañaga - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +{ + "name": "Sale Order Rental", + "version": "12.0.1.0.0", + "license": "AGPL-3", + "depends": [ + "sale_management", + "stock", + ], + "author": "AvanzOSC", + "website": "http://www.avanzosc.es", + "category": "Sales", + "data": [ + "security/ir.model.access.csv", + "views/sale_order_view.xml", + "views/stock_picking_view.xml", + "views/account_invoice_view.xml", + ], + "installable": True, +} diff --git a/sale_order_rental/i18n/es.po b/sale_order_rental/i18n/es.po new file mode 100644 index 00000000..fd67e816 --- /dev/null +++ b/sale_order_rental/i18n/es.po @@ -0,0 +1,96 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_order_rental +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-07-29 08:23+0000\n" +"PO-Revision-Date: 2019-07-29 08:23+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: sale_order_rental +#: model:ir.model.fields,field_description:sale_order_rental.field_account_invoice__expected_delivery_date +#: model:ir.model.fields,field_description:sale_order_rental.field_account_invoice_line__expected_delivery_date +#: model:ir.model.fields,field_description:sale_order_rental.field_sale_order__expected_delivery_date +#: model:ir.model.fields,field_description:sale_order_rental.field_sale_order_line__expected_delivery_date +#: model:ir.model.fields,field_description:sale_order_rental.field_stock_move__expected_delivery_date +#: model:ir.model.fields,field_description:sale_order_rental.field_stock_picking__expected_delivery_date +msgid "Expected delivery date" +msgstr "Fecha inicio" + +#. module: sale_order_rental +#: model:ir.model.fields,field_description:sale_order_rental.field_account_invoice__expected_end_date +#: model:ir.model.fields,field_description:sale_order_rental.field_account_invoice_line__expected_end_date +#: model:ir.model.fields,field_description:sale_order_rental.field_sale_order__expected_end_date +#: model:ir.model.fields,field_description:sale_order_rental.field_sale_order_line__expected_end_date +#: model:ir.model.fields,field_description:sale_order_rental.field_stock_move__expected_end_date +#: model:ir.model.fields,field_description:sale_order_rental.field_stock_picking__expected_end_date +msgid "Expected end date" +msgstr "Fecha fin" + +#. module: sale_order_rental +#: model:ir.model,name:sale_order_rental.model_account_invoice +msgid "Invoice" +msgstr "Factura" + +#. module: sale_order_rental +#: model:ir.model,name:sale_order_rental.model_account_invoice_line +msgid "Invoice Line" +msgstr "Linea de Factura" + +#. module: sale_order_rental +#: model:ir.model.fields,field_description:sale_order_rental.field_account_invoice_line__rental_days +#: model:ir.model.fields,field_description:sale_order_rental.field_sale_order__rental_days +#: model:ir.model.fields,field_description:sale_order_rental.field_sale_order_line__rental_days +#: model:ir.model.fields,field_description:sale_order_rental.field_stock_move__rental_days +#: model:ir.model.fields,field_description:sale_order_rental.field_stock_picking__rental_days +msgid "Rental days" +msgstr "Días de alquiler" + +#. module: sale_order_rental +#: model:ir.model,name:sale_order_rental.model_stock_return_picking +msgid "Return Picking" +msgstr "Albarán de devolución" + +#. module: sale_order_rental +#: model:ir.model,name:sale_order_rental.model_sale_order +msgid "Sale Order" +msgstr "Pedido de venta" + +#. module: sale_order_rental +#: model:ir.model.fields,field_description:sale_order_rental.field_account_invoice__sale_order_id +msgid "Sale order" +msgstr "Pedido" + +#. module: sale_order_rental +#: model:ir.model.fields,field_description:sale_order_rental.field_account_invoice_line__sale_order_line_id +msgid "Sale order line" +msgstr "Línea de Pedido de Venta" + +#. module: sale_order_rental +#: model:ir.model,name:sale_order_rental.model_sale_order_line +msgid "Sales Order Line" +msgstr "Línea de pedido de venta" + +#. module: sale_order_rental +#: model:ir.model,name:sale_order_rental.model_stock_move +msgid "Stock Move" +msgstr "Movimiento de existencias" + +#. module: sale_order_rental +#: model:ir.model,name:sale_order_rental.model_stock_picking +msgid "Transfer" +msgstr "Transferir" + +#. module: sale_order_rental +#: model:ir.model.fields,field_description:sale_order_rental.field_account_invoice__rental_days +msgid "rental days" +msgstr "" + diff --git a/sale_order_rental/i18n/sale_order_rental.pot b/sale_order_rental/i18n/sale_order_rental.pot new file mode 100644 index 00000000..153c4ebb --- /dev/null +++ b/sale_order_rental/i18n/sale_order_rental.pot @@ -0,0 +1,96 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_order_rental +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-07-29 08:21+0000\n" +"PO-Revision-Date: 2019-07-29 08:21+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: sale_order_rental +#: model:ir.model.fields,field_description:sale_order_rental.field_account_invoice__expected_delivery_date +#: model:ir.model.fields,field_description:sale_order_rental.field_account_invoice_line__expected_delivery_date +#: model:ir.model.fields,field_description:sale_order_rental.field_sale_order__expected_delivery_date +#: model:ir.model.fields,field_description:sale_order_rental.field_sale_order_line__expected_delivery_date +#: model:ir.model.fields,field_description:sale_order_rental.field_stock_move__expected_delivery_date +#: model:ir.model.fields,field_description:sale_order_rental.field_stock_picking__expected_delivery_date +msgid "Expected delivery date" +msgstr "Fecha inicio" + +#. module: sale_order_rental +#: model:ir.model.fields,field_description:sale_order_rental.field_account_invoice__expected_end_date +#: model:ir.model.fields,field_description:sale_order_rental.field_account_invoice_line__expected_end_date +#: model:ir.model.fields,field_description:sale_order_rental.field_sale_order__expected_end_date +#: model:ir.model.fields,field_description:sale_order_rental.field_sale_order_line__expected_end_date +#: model:ir.model.fields,field_description:sale_order_rental.field_stock_move__expected_end_date +#: model:ir.model.fields,field_description:sale_order_rental.field_stock_picking__expected_end_date +msgid "Expected end date" +msgstr "Fecha fin" + +#. module: sale_order_rental +#: model:ir.model,name:sale_order_rental.model_account_invoice +msgid "Invoice" +msgstr "Factura" + +#. module: sale_order_rental +#: model:ir.model,name:sale_order_rental.model_account_invoice_line +msgid "Invoice Line" +msgstr "Línea de factura" + +#. module: sale_order_rental +#: model:ir.model.fields,field_description:sale_order_rental.field_account_invoice_line__rental_days +#: model:ir.model.fields,field_description:sale_order_rental.field_sale_order__rental_days +#: model:ir.model.fields,field_description:sale_order_rental.field_sale_order_line__rental_days +#: model:ir.model.fields,field_description:sale_order_rental.field_stock_move__rental_days +#: model:ir.model.fields,field_description:sale_order_rental.field_stock_picking__rental_days +msgid "Rental days" +msgstr "Dias de alquiler" + +#. module: sale_order_rental +#: model:ir.model,name:sale_order_rental.model_stock_return_picking +msgid "Return Picking" +msgstr "Albarán de devolución" + +#. module: sale_order_rental +#: model:ir.model,name:sale_order_rental.model_sale_order +msgid "Sale Order" +msgstr "Pedido de venta" + +#. module: sale_order_rental +#: model:ir.model.fields,field_description:sale_order_rental.field_account_invoice__sale_order_id +msgid "Sale order" +msgstr "Pedido de venta" + +#. module: sale_order_rental +#: model:ir.model.fields,field_description:sale_order_rental.field_account_invoice_line__sale_order_line_id +msgid "Sale order line" +msgstr "Linea de pedido de venta" + +#. module: sale_order_rental +#: model:ir.model,name:sale_order_rental.model_sale_order_line +msgid "Sales Order Line" +msgstr "Linea de pedido de venta" + +#. module: sale_order_rental +#: model:ir.model,name:sale_order_rental.model_stock_move +msgid "Stock Move" +msgstr "Movimiento de stock" + +#. module: sale_order_rental +#: model:ir.model,name:sale_order_rental.model_stock_picking +msgid "Transfer" +msgstr "Transferir" + +#. module: sale_order_rental +#: model:ir.model.fields,field_description:sale_order_rental.field_account_invoice__rental_days +msgid "rental days" +msgstr "Dias de alquiler" + diff --git a/sale_order_rental/models/__init__.py b/sale_order_rental/models/__init__.py new file mode 100644 index 00000000..5f20f2c0 --- /dev/null +++ b/sale_order_rental/models/__init__.py @@ -0,0 +1,3 @@ +from . import sale_order +from . import stock +from . import account_invoice diff --git a/sale_order_rental/models/account_invoice.py b/sale_order_rental/models/account_invoice.py new file mode 100644 index 00000000..b93467ed --- /dev/null +++ b/sale_order_rental/models/account_invoice.py @@ -0,0 +1,103 @@ +# Copyright 2019 Oihana Larrañaga - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +from odoo import models, fields, api + + +class AccountInvoice(models.Model): + _inherit = 'account.invoice' + + sale_order_id = fields.Many2one( + string='Sale order', comodel_name='sale.order') + expected_delivery_date = fields.Date( + string='Expected delivery date', + related='sale_order_id.expected_delivery_date') + expected_end_date = fields.Date( + string='Expected end date', related='sale_order_id.expected_end_date') + rental_days = fields.Integer( + string='rental days', related='sale_order_id.rental_days') + + @api.multi + def get_taxes_values(self): + tax_grouped = {} + round_curr = self.currency_id.round + for line in self.invoice_line_ids: + if not line.account_id: + continue + price_unit = line.price_unit * (1 - (line.discount or 0.0) / 100.0) + if line.rental_days: + taxes = line.invoice_line_tax_ids.compute_all( + price_unit, self.currency_id, + line.quantity * line.rental_days, + line.product_id, self.partner_id)['taxes'] + else: + taxes = line.invoice_line_tax_ids.compute_all( + price_unit, self.currency_id, line.quantity, + line.product_id, self.partner_id)['taxes'] + for tax in taxes: + val = self._prepare_tax_line_vals(line, tax) + key = self.env['account.tax'].browse( + tax['id']).get_grouping_key(val) + if key not in tax_grouped: + tax_grouped[key] = val + tax_grouped[key]['base'] = round_curr(val['base']) + else: + tax_grouped[key]['amount'] += val['amount'] + tax_grouped[key]['base'] += round_curr(val['base']) + return tax_grouped + + +class AccountInvoiceLine(models.Model): + _inherit = 'account.invoice.line' + + expected_delivery_date = fields.Date( + string='Expected delivery date', + compute='_compute_expected_delivery_date', store=True) + expected_end_date = fields.Date( + string='Expected end date', + compute='_compute_expected_end_date', store=True) + rental_days = fields.Integer( + string='Rental days', + compute='_compute_rental_days', store=True) + + @api.depends('sale_line_ids', 'sale_line_ids.expected_delivery_date') + def _compute_expected_delivery_date(self): + for line in self: + for sale_line in line.sale_line_ids.filtered( + lambda l: l.expected_delivery_date): + line.expected_delivery_date = sale_line.expected_delivery_date + + @api.depends('sale_line_ids', 'sale_line_ids.expected_end_date') + def _compute_expected_end_date(self): + for line in self: + for sale_line in line.sale_line_ids.filtered( + lambda l: l.expected_end_date): + line.expected_end_date = sale_line.expected_end_date + + @api.depends('sale_line_ids', 'sale_line_ids.rental_days') + def _compute_rental_days(self): + for line in self: + for sale_line in line.sale_line_ids.filtered( + lambda l: l.rental_days): + line.rental_days = sale_line.rental_days + + @api.depends('price_unit', 'discount', 'invoice_line_tax_ids', 'quantity', + 'rental_days', 'product_id', 'invoice_id.partner_id', + 'invoice_id.currency_id', 'invoice_id.company_id', + 'invoice_id.date_invoice', 'invoice_id.date') + def _compute_price(self): + for line in self: + if line.rental_days: + price = line.price_unit * (1 - (line.discount or 0.0) / 100.0) + taxes = line.invoice_line_tax_ids.compute_all( + price, line.invoice_id.currency_id, + line.quantity * line.rental_days, + product=line.product_id, + partner=line.invoice_id.partner_shipping_id) + line.update({ + 'price_tax': sum( + t.get('amount', 0.0) for t in taxes.get('taxes', [])), + 'price_total': taxes['total_included'], + 'price_subtotal': taxes['total_excluded'], + }) + else: + super(AccountInvoiceLine, line)._compute_price() diff --git a/sale_order_rental/models/sale_order.py b/sale_order_rental/models/sale_order.py new file mode 100644 index 00000000..d3daa829 --- /dev/null +++ b/sale_order_rental/models/sale_order.py @@ -0,0 +1,143 @@ +# Copyright 2019 Oihana Larrañaga - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +from odoo import models, fields, api +from odoo.exceptions import UserError + + +class SaleOrder(models.Model): + _inherit = 'sale.order' + + expected_delivery_date = fields.Date( + string='Expected delivery date') + expected_end_date = fields.Date( + string='Expected end date') + rental_days = fields.Integer( + string='Rental days', compute='_compute_rental_days', store=True) + + @api.depends('expected_delivery_date', 'expected_end_date') + def _compute_rental_days(self): + for order in self.filtered(lambda o: o.expected_delivery_date and + o.expected_end_date): + order.rental_days = abs( + order.expected_end_date-order.expected_delivery_date + ).days + 1 + + @api.onchange('expected_delivery_date') + def onchange_expected_delivery_date(self): + if self.expected_delivery_date: + self.commitment_date = fields.Datetime.to_datetime( + self.expected_delivery_date) + for line in self.order_line: + line.expected_delivery_date = self.expected_delivery_date + + @api.onchange('expected_end_date') + def onchange_expected_end_date(self): + if self.expected_delivery_date > self.expected_end_date: + raise UserError( + "Expected end date must be greater " + "than expected delivery date") + if self.expected_end_date: + for line in self.order_line: + line.expected_end_date = self.expected_end_date + + @api.multi + def action_confirm(self): + res = super(SaleOrder, self).action_confirm() + for sale in self: + for picking in sale.picking_ids.filtered( + lambda l: l.expected_end_date): + vals = { + 'location_id': picking.location_dest_id.id, + 'location_dest_id': picking.location_id.id, + 'picking_type_id': + picking.picking_type_id.return_picking_type_id.id} + if picking.expected_end_date: + vals['scheduled_date'] = ( + "{} 08:00:00".format(picking.expected_end_date)) + new_picking = picking.copy(vals) + for move in new_picking.move_lines: + if move.expected_end_date: + vals = { + 'location_id': new_picking.location_id.id, + 'location_dest_id': + new_picking.location_dest_id.id} + if move.expected_end_date: + vals['date_expected'] = ( + "{} 08:00:00".format(move.expected_end_date)) + move.write(vals) + move._action_confirm() + if not move.expected_end_date: + move.unlink() + return res + + @api.multi + def _prepare_invoice(self): + invoice_vals = super(SaleOrder, self)._prepare_invoice() + invoice_vals['sale_order_id'] = self.id + return invoice_vals + + +class SaleOrderLine(models.Model): + _inherit = 'sale.order.line' + + expected_delivery_date = fields.Date( + string='Expected delivery date') + expected_end_date = fields.Date( + string='Expected end date', ) + rental_days = fields.Integer( + string='Rental days', compute='_compute_rental_days', store=True) + + @api.depends('expected_delivery_date', 'expected_end_date') + def _compute_rental_days(self): + for line in self.filtered(lambda l: l.expected_delivery_date and + l.expected_end_date): + if line.expected_delivery_date > line.expected_end_date: + raise UserError( + "Expected end date must be greater " + "than expected delivery date") + else: + line.rental_days = abs( + line.expected_end_date - line.expected_delivery_date + ).days + 1 + + @api.multi + @api.onchange('product_id') + def product_id_change(self): + result = super(SaleOrderLine, self).product_id_change() + if self.order_id.expected_delivery_date: + self.expected_delivery_date = self.order_id.expected_delivery_date + if self.order_id.expected_end_date: + self.expected_end_date = self.order_id.expected_end_date + return result + + @api.depends('product_uom_qty', 'discount', 'price_unit', 'tax_id', + 'rental_days') + def _compute_amount(self): + for line in self: + if line.rental_days: + price = line.price_unit * (1 - (line.discount or 0.0) / 100.0) + taxes = line.tax_id.compute_all( + price, line.order_id.currency_id, + line.product_uom_qty * line.rental_days, + product=line.product_id, + partner=line.order_id.partner_shipping_id) + line.update({ + 'price_tax': sum( + t.get('amount', 0.0) for t in taxes.get('taxes', [])), + 'price_total': taxes['total_included'], + 'price_subtotal': taxes['total_excluded'], + }) + else: + super(SaleOrderLine, line)._compute_amount() + + @api.multi + def invoice_line_create_vals(self, invoice_id, qty): + res = super( + SaleOrderLine, self).invoice_line_create_vals(invoice_id, qty) + for result in res: + if result.get('sale_line_ids', False): + a = result.get('sale_line_ids') + sale_line_id = a[0][2][0] + if sale_line_id: + result['sale_order_line_id'] = sale_line_id + return res diff --git a/sale_order_rental/models/stock.py b/sale_order_rental/models/stock.py new file mode 100644 index 00000000..ee955a87 --- /dev/null +++ b/sale_order_rental/models/stock.py @@ -0,0 +1,26 @@ +# Copyright 2019 Oihana Larrañaga - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +from odoo import models, fields + + +class StockPicking(models.Model): + _inherit = 'stock.picking' + + expected_delivery_date = fields.Date( + related='sale_id.expected_delivery_date') + expected_end_date = fields.Date( + string='Expected end date', related='sale_id.expected_end_date') + rental_days = fields.Integer( + related='sale_id.rental_days') + + +class StockMove(models.Model): + _inherit = 'stock.move' + + expected_delivery_date = fields.Date( + related='sale_line_id.expected_delivery_date', readonly=False) + expected_end_date = fields.Date( + string='Expected end date', + related='sale_line_id.expected_end_date', readonly=False) + rental_days = fields.Integer( + related='sale_line_id.rental_days') diff --git a/sale_order_rental/security/ir.model.access.csv b/sale_order_rental/security/ir.model.access.csv new file mode 100644 index 00000000..0921b85f --- /dev/null +++ b/sale_order_rental/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink +sale_order_model_manager,sale_order_model_manager,model_sale_order,,1,1,1,1 +sale_order_model_user,sale_order_model_user,model_sale_order,,1,0,0,0 diff --git a/sale_order_rental/static/img/enviado.png b/sale_order_rental/static/img/enviado.png new file mode 100644 index 0000000000000000000000000000000000000000..412cb943c82f3bca5ad36f8b811b88f89e444ba3 GIT binary patch literal 14165 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

u}_f0;!B!hX!1=tk#!$BF^7uoVUe& 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 literal 0 HcmV?d00001 diff --git a/sale_order_rental/views/account_invoice_view.xml b/sale_order_rental/views/account_invoice_view.xml new file mode 100755 index 00000000..5f07f805 --- /dev/null +++ b/sale_order_rental/views/account_invoice_view.xml @@ -0,0 +1,19 @@ + + + + account.invoice + + + + + + + + + + + + + + + diff --git a/sale_order_rental/views/sale_order_view.xml b/sale_order_rental/views/sale_order_view.xml new file mode 100755 index 00000000..508a2949 --- /dev/null +++ b/sale_order_rental/views/sale_order_view.xml @@ -0,0 +1,41 @@ + + + + sale.order + + + + + + + + + + + sale.order + + + + + + + + + + + sale.order + + + + + + + + + + + + + + + diff --git a/sale_order_rental/views/stock_picking_view.xml b/sale_order_rental/views/stock_picking_view.xml new file mode 100755 index 00000000..3480b682 --- /dev/null +++ b/sale_order_rental/views/stock_picking_view.xml @@ -0,0 +1,30 @@ + + + + stock.picking + + + + + + + + + + + + + + + + stock.picking + + + + + + + + + + diff --git a/sale_order_rental/wizards/__init__.py b/sale_order_rental/wizards/__init__.py new file mode 100644 index 00000000..ad0b47c2 --- /dev/null +++ b/sale_order_rental/wizards/__init__.py @@ -0,0 +1 @@ +from . import stock_picking_return diff --git a/sale_order_rental/wizards/stock_picking_return.py b/sale_order_rental/wizards/stock_picking_return.py new file mode 100644 index 00000000..9cba4ad5 --- /dev/null +++ b/sale_order_rental/wizards/stock_picking_return.py @@ -0,0 +1,17 @@ +# Copyright 2019 Oihana Larrañaga - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from odoo import fields, models + + +class ReturnPicking(models.TransientModel): + _inherit = 'stock.return.picking' + + def _prepare_move_default_values(self, return_line, new_picking): + vals = super(ReturnPicking, self)._prepare_move_default_values( + return_line, new_picking) + vals.update({ + 'date_expected': fields.Datetime.to_datetime( + self.picking_id.sale_id.expected_end_date), + }) + return vals