From 3e8df94ede71815aeea1221585ff70c40987839c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adasat=20Torres=20de=20Le=C3=B3n?= Date: Mon, 16 Sep 2024 12:01:00 +0100 Subject: [PATCH] [MIG] rental_base : Migration to 16.0 --- rental_base/README.rst | 85 +++++++++++++++++ rental_base/__init__.py | 1 - rental_base/__manifest__.py | 2 +- rental_base/models/product.py | 6 ++ rental_base/models/sale.py | 75 ++++++++------- rental_base/tests/stock_common.py | 70 +++++++------- .../tests/test_update_time_rental_order.py | 29 +++--- rental_base/views/sale_view.xml | 76 +++++---------- rental_base/wizard/update_sale_line_date.py | 95 +++++++++---------- 9 files changed, 255 insertions(+), 184 deletions(-) diff --git a/rental_base/README.rst b/rental_base/README.rst index cbe24209..bed50add 100644 --- a/rental_base/README.rst +++ b/rental_base/README.rst @@ -1,3 +1,33 @@ +=========== +Rental Base +=========== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:0bc702920244f4991b1ecfd919d317650996018e336a54f6caabed03622f58f0 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fvertical--rental-lightgray.png?logo=github + :target: https://github.com/OCA/vertical-rental/tree/16.0/rental_base + :alt: OCA/vertical-rental +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/vertical-rental-16-0/vertical-rental-16-0-rental_base + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/vertical-rental&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + Rental Base ==================================================== @@ -16,6 +46,14 @@ Base Module for Rental Management This module provides a new menu for rental management. It is based on the sale_rental module that currently can be found in sale-workflow repository. +**Table of contents** + +.. contents:: + :local: + +Usage +===== + Usage ----- @@ -40,6 +78,10 @@ Create a rental order: Please also see the usage section of sale_rental module. +Changelog +========= + + Changelog --------- @@ -48,3 +90,46 @@ Changelog - ac980b89 2022-02-28 17:36:28 +0100 cpatel@elegosoft.com [FIX][IMP] correct code, (issue#4516) - 4509f78a 2022-02-23 20:48:33 +0100 wagner@elegosoft.com (origin/feature_4516_add_files_ported_from_v12_v14, feature_4516_add_files_ported_from_v12_v14) add files ported to v14 by cpatel and khanhbui (issue #4516) +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 to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* elego Software Solutions GmbH + +Contributors +~~~~~~~~~~~~ + + +Contributors +------------ + +elego Software Solutions GmbH, Odoo Community Association (OCA) + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/vertical-rental `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/rental_base/__init__.py b/rental_base/__init__.py index 75749508..7eb56335 100644 --- a/rental_base/__init__.py +++ b/rental_base/__init__.py @@ -1,4 +1,3 @@ # Part of rental-vertical See LICENSE file for full copyright and licensing details. from . import models -from . import tests from . import wizard diff --git a/rental_base/__manifest__.py b/rental_base/__manifest__.py index 10e3ae9b..99b23dcd 100644 --- a/rental_base/__manifest__.py +++ b/rental_base/__manifest__.py @@ -2,7 +2,7 @@ { "name": "Rental Base", - "version": "14.0.1.0.1", + "version": "16.0.1.0.0", "category": "Rental", "summary": "Manage Rental of Products", "author": "elego Software Solutions GmbH, Odoo Community Association (OCA)", diff --git a/rental_base/models/product.py b/rental_base/models/product.py index ffaffe8f..d545121e 100644 --- a/rental_base/models/product.py +++ b/rental_base/models/product.py @@ -7,3 +7,9 @@ class ProductTemplate(models.Model): _inherit = "product.template" rental = fields.Boolean("Can be Rent") + + +class ProductProduct(models.Model): + _inherit = "product.product" + + rental = fields.Boolean("Can be Rent") diff --git a/rental_base/models/sale.py b/rental_base/models/sale.py index d52fbc55..e6869afa 100644 --- a/rental_base/models/sale.py +++ b/rental_base/models/sale.py @@ -1,5 +1,4 @@ # Part of rental-vertical See LICENSE file for full copyright and licensing details. - import datetime from odoo import _, api, exceptions, fields, models @@ -11,14 +10,12 @@ class SaleOrder(models.Model): _inherit = "sale.order" default_start_date = fields.Date( - string="Default Start Date", compute="_compute_default_start_date", readonly=False, store=True, ) default_end_date = fields.Date( - string="Default End Date", compute="_compute_default_end_date", readonly=False, store=True, @@ -106,49 +103,54 @@ def _check_sale_line_rental(self): if not line.extension_rental_id: raise ValidationError( _( - 'Missing "Rental to Extend" on the sale order line ' - "with rental service %s." + 'Missing "Rental to Extend" on the sale order line' + " with rental service %(name)s." ) - % line.product_id.name + % {"name": line.product_id.name} ) if line.rental_qty != line.extension_rental_id.rental_qty: raise ValidationError( _( - "On the sale order line with rental service %s, " - "you are trying to extend a rental with a rental " - "quantity (%s) that is different from the quantity " - "of the original rental (%s). This is not supported." - ) - % ( - line.product_id.name, - line.rental_qty, - line.extension_rental_id.rental_qty, + "On the sale order line with" + " rental service %(name)s" + " ,you are trying to extend a " + "rental with a rental " + "quantity (%(rental_qty)s) " + "that is different from the quantity " + "of the original rental " + "(%(ext_rental_qty)s). " + "This is not supported." ) + % { + "name": line.product_id.name, + "rental_qty": line.rental_qty, + "ext_rental_qty": line.extension_rental_id.rental_qty, + } ) if line.rental_type in ("new_rental", "rental_extension"): if not line.product_id.rented_product_id: raise ValidationError( _( 'On the "new rental" sale order line with product ' - '"%s", we should have a rental service product!' + '"%(name)s", we should have a rental service product!' ) - % (line.product_id.name) + % {"name": line.product_id.name} ) elif line.sell_rental_id: if line.product_uom_qty != line.sell_rental_id.rental_qty: raise ValidationError( _( - "On the sale order line with product %s " + "On the sale order line with product %(name)s " "you are trying to sell a rented product with a " - "quantity (%s) that is different from the rented " - "quantity (%s). This is not supported." - ) - % ( - line.product_id.name, - line.product_uom_qty, - line.sell_rental_id.rental_qty, + "quantity (%(qty)s) that is different from the rented " + "quantity (%(sell_rental_qty)s). This is not supported." ) + % { + "name": line.product_id.name, + "qty": line.product_uom_qty, + "sell_rental_qty": line.sell_rental_id.rental_qty, + } ) def _prepare_invoice_line(self, **optional_values): @@ -218,10 +220,10 @@ def update_start_end_date(self, date_start, date_end): ]: raise exceptions.UserError( _( - "Outgoing shipment is in state %s. You cannot change \ - the start date anymore." + "Outgoing shipment is in state %(state)s." + " You cannot change the start date anymore." ) - % rental.out_move_id.state + % {"state": rental.out_move_id.state} ) rental.out_move_id.date = datetime_start if rentals and date_end: @@ -235,10 +237,10 @@ def update_start_end_date(self, date_start, date_end): ]: raise exceptions.UserError( _( - "Incoming shipment is in state %s. You cannot change \ - the end date anymore." + "Incoming shipment is in state %s." + " You cannot change the end date anymore." ) - % rental.in_move_id.state + % {"state": rental.in_move_id.state} ) rental.in_move_id.date = datetime_end @@ -293,14 +295,17 @@ def write(self, values): if messages: messages.append( _( - "\nOrder: %s\n" - "Line with product: '%s'\n\n" + "\nOrder: %(order)s\n" + "Line with product: '%(product)s'\n\n" "Please use instead the button 'Update Times' " "in the order to correctly update the order " "line's times, its timeline entry, contract and " "its stock moves and pickings as required." ) - % (sol.order_id.name, sol.product_id.display_name) + % { + "order": sol.order_id.name, + "product": sol.product_id.display_name, + } ) raise exceptions.UserError("\n".join(messages)) - return super(SaleOrderLine, self).write(values) + return super().write(values) diff --git a/rental_base/tests/stock_common.py b/rental_base/tests/stock_common.py index 30b68ea7..73216afc 100644 --- a/rental_base/tests/stock_common.py +++ b/rental_base/tests/stock_common.py @@ -4,32 +4,33 @@ class RentalStockCommon(common.TransactionCase): - def setUp(self): - super().setUp() - + @classmethod + def setUpClass(cls): + super().setUpClass() # Rental Type, Picking Type, Locations and Uoms - self.category_all = self.env.ref("product.product_category_all") - self.rental_sale_type = self.env.ref("rental_base.rental_sale_type") - self.picking_type_in = self.env.ref("stock.picking_type_in") - self.picking_type_out = self.env.ref("stock.picking_type_out") - self.stock_location = self.env.ref("stock.stock_location_stock") - self.supplier_location = self.env.ref("stock.stock_location_suppliers") - self.customer_location = self.env.ref("stock.stock_location_customers") - self.uom_hour = self.env.ref("uom.product_uom_hour") - self.uom_day = self.env.ref("uom.product_uom_day") - self.uom_month = self.env.ref("rental_base.product_uom_month") - self.uom_unit = self.env.ref("uom.product_uom_unit") - self.uom_kgm = self.env.ref("uom.product_uom_kgm") - self.warehouse0 = self.env.ref("stock.warehouse0") - self.PartnerObj = self.env["res.partner"] - self.partnerA = self.PartnerObj.create( + cls.category_all = cls.env.ref("product.product_category_all") + cls.rental_sale_type = cls.env.ref("rental_base.rental_sale_type") + cls.picking_type_in = cls.env.ref("stock.picking_type_in") + cls.picking_type_out = cls.env.ref("stock.picking_type_out") + cls.stock_location = cls.env.ref("stock.stock_location_stock") + cls.supplier_location = cls.env.ref("stock.stock_location_suppliers") + cls.customer_location = cls.env.ref("stock.stock_location_customers") + cls.uom_hour = cls.env.ref("uom.product_uom_hour") + cls.uom_day = cls.env.ref("uom.product_uom_day") + cls.uom_month = cls.env.ref("rental_base.product_uom_month") + cls.uom_unit = cls.env.ref("uom.product_uom_unit") + cls.uom_kgm = cls.env.ref("uom.product_uom_kgm") + cls.warehouse0 = cls.env.ref("stock.warehouse0") + cls.PartnerObj = cls.env["res.partner"] + cls.partnerA = cls.PartnerObj.create( { "name": "Partner A", - "country_id": self.env.ref("base.de").id, + "country_id": cls.env.ref("base.de").id, } ) - def _create_rental_service_day(self, product): + @classmethod + def _create_rental_service_day(cls, product): values = { "hw_product_id": product.id, "name": "Rental of %s (Day)" % product.name, @@ -37,17 +38,17 @@ def _create_rental_service_day(self, product): "copy_image": True, } res = ( - self.env["create.rental.product"] + cls.env["create.rental.product"] .with_context(active_model="product.product", active_id=product.id) .create(values) .create_rental_product() ) - rental_service = self.env["product.product"].browse(res["res_id"]) + rental_service = cls.env["product.product"].browse(res["res_id"]) rental_service.write( { - "uom_id": self.uom_day.id, - "uom_po_id": self.uom_day.id, + "uom_id": cls.uom_day.id, + "uom_po_id": cls.uom_day.id, "income_analytic_account_id": product.income_analytic_account_id.id, "list_price": 100, } @@ -55,8 +56,9 @@ def _create_rental_service_day(self, product): return rental_service - def _create_move(self, product, src_location, dst_location, **values): - Move = self.env["stock.move"] + @classmethod + def _create_move(cls, product, src_location, dst_location, **values): + Move = cls.env["stock.move"] move = Move.new( { "product_id": product.id, @@ -69,27 +71,28 @@ def _create_move(self, product, src_location, dst_location, **values): move_values.update(**values) return Move.create(move_values) - def _create_rental_order(self, partner_id, date_start, date_end, qty=1): + @classmethod + def _create_rental_order(cls, partner_id, date_start, date_end, qty=1): """ Create a Rental Order with Product (self.service_rental) """ date_qty = (date_end - date_start).days + 1 - rental_order = self.env["sale.order"].create( + rental_order = cls.env["sale.order"].create( { - "type_id": self.rental_sale_type.id, + "type_id": cls.rental_sale_type.id, "partner_id": partner_id, "partner_invoice_id": partner_id, "partner_shipping_id": partner_id, - "pricelist_id": self.env.ref("product.list0").id, + "pricelist_id": cls.env.ref("product.list0").id, "picking_policy": "direct", - "warehouse_id": self.warehouse0.id, + "warehouse_id": cls.warehouse0.id, "order_line": [ ( 0, 0, { "name": "Service for Rental", - "product_id": self.service_rental.id, + "product_id": cls.service_rental.id, "rental": True, "rental_type": "new_rental", "rental_qty": qty, @@ -97,11 +100,10 @@ def _create_rental_order(self, partner_id, date_start, date_end, qty=1): "start_date": date_start, "end_date": date_end, "price_unit": 100, - "product_uom": self.uom_day.id, + "product_uom": cls.uom_day.id, }, ) ], } ) - self.assertEqual(rental_order.state, "draft") return rental_order diff --git a/rental_base/tests/test_update_time_rental_order.py b/rental_base/tests/test_update_time_rental_order.py index 14fcd75c..f62a751f 100644 --- a/rental_base/tests/test_update_time_rental_order.py +++ b/rental_base/tests/test_update_time_rental_order.py @@ -6,25 +6,26 @@ class TestUpdateTimeRentalOrder(RentalStockCommon): - def setUp(self): - super().setUp() - ProductObj = self.env["product.product"] - self.product_rental = ProductObj.create( + @classmethod + def setUpClass(cls): + super().setUpClass() + ProductObj = cls.env["product.product"] + cls.product_rental = ProductObj.create( { "name": "Rental Product", "type": "product", - "categ_id": self.category_all.id, + "categ_id": cls.category_all.id, } ) # rental service product - self.service_rental = self._create_rental_service_day(self.product_rental) + cls.service_rental = cls._create_rental_service_day(product=cls.product_rental) # dates - self.date_0101 = fields.Date.from_string("2021-01-01") - self.date_0110 = fields.Date.from_string("2021-01-10") - self.date_0102 = fields.Date.from_string("2021-01-02") - self.date_0111 = fields.Date.from_string("2021-01-11") - self.date_0103 = fields.Date.from_string("2021-01-03") - self.date_0112 = fields.Date.from_string("2021-01-12") + cls.date_0101 = fields.Date.from_string("2021-01-01") + cls.date_0110 = fields.Date.from_string("2021-01-10") + cls.date_0102 = fields.Date.from_string("2021-01-02") + cls.date_0111 = fields.Date.from_string("2021-01-11") + cls.date_0103 = fields.Date.from_string("2021-01-03") + cls.date_0112 = fields.Date.from_string("2021-01-12") def test_00_update_time_rental_order(self): # rental order @@ -54,7 +55,7 @@ def test_00_update_time_rental_order(self): wizard_1 = ( self.env["update.sale.line.date"] .with_context( - { + **{ "active_model": "sale.order", "active_ids": rental_order_1.ids, } @@ -115,7 +116,7 @@ def test_00_update_time_rental_order(self): wizard_2 = ( self.env["update.sale.line.date"] .with_context( - { + **{ "active_model": "sale.order", "active_ids": rental_order_1.ids, } diff --git a/rental_base/views/sale_view.xml b/rental_base/views/sale_view.xml index 24625c58..0875fd3b 100644 --- a/rental_base/views/sale_view.xml +++ b/rental_base/views/sale_view.xml @@ -1,6 +1,5 @@ - rental_base.sale_rental @@ -24,12 +23,12 @@ - rental_base.sale_start_end_dates sale.order - 110 + 110 + @@ -47,22 +46,17 @@ - - rental_base.sale_stock - sale.order - - - - {'invisible': 1} - - + rental_base.sale_stock + sale.order + + + + {'invisible': 1} + + - rental_base.sale_order_type @@ -76,7 +70,6 @@ - rental_base.view_order_form sale.order @@ -105,7 +98,6 @@ > {'invisible': 1} - - - - further_rental_info - {'invisible': 1} @@ -148,10 +133,7 @@ {'invisible': 1} - - + {'invisible': 1} @@ -185,7 +167,6 @@ name="attrs" >{'invisible': [('display_type', '=', False)]} - order_info @@ -245,8 +226,10 @@ /> - - + @@ -270,7 +253,6 @@ domain="[('rented_product_id', '=', product_id), ('state', '=', 'out')]" /> - - - + Day(s) - - - - - diff --git a/rental_base/wizard/update_sale_line_date.py b/rental_base/wizard/update_sale_line_date.py index 433b449e..636e98ed 100644 --- a/rental_base/wizard/update_sale_line_date.py +++ b/rental_base/wizard/update_sale_line_date.py @@ -12,31 +12,20 @@ class UpdateSaleLineDateLine(models.TransientModel): required=True, ) - sequence = fields.Integer( - string="Sequence", - ) + sequence = fields.Integer() order_line_id = fields.Many2one( comodel_name="sale.order.line", required=True, ) - date_start = fields.Date( - string="Date Start", - ) + date_start = fields.Date() - date_end = fields.Date( - string="Date End", - ) + date_end = fields.Date() - product_id = fields.Many2one( - comodel_name="product.product", - string="Product", - ) + product_id = fields.Many2one(comodel_name="product.product") - change = fields.Boolean( - string="Change", - ) + change = fields.Boolean() class UpdateSaleLineDate(models.TransientModel): @@ -44,22 +33,18 @@ class UpdateSaleLineDate(models.TransientModel): _description = "Wizard for updating sale order line dates" date_start = fields.Date( - string="Date Start", required=True, ) date_end = fields.Date( - string="Date End", required=True, ) order_id = fields.Many2one( comodel_name="sale.order", - string="Sale Order", ) date_in_line = fields.Boolean( - string="Date in Lines", help="If set, you can set an individual date in " "every selected position.", ) @@ -153,23 +138,30 @@ def action_confirm(self): if self.all_line: if self.date_in_line: for line in self.line_ids: - message_body += _("
  • %s: %s - %s -> %s - %s
  • ") % ( - line.order_line_id.product_id.name, - line.order_line_id.start_date, - line.order_line_id.end_date, - line.date_start, - line.date_end, - ) + message_body += _( + "
  • %(name)s: %(start_date)s - %(end_date)s->" + "%(date_start)s - %(date_end)s
  • " + ) % { + "name": line.order_line_id.product_id.name, + "start_date": line.order_line_id.start_date, + "end_date": line.order_line_id.end_date, + "date_start": line.date_start, + "date_end": line.date_end, + } line.order_line_id.update_start_end_date( line.date_start, line.date_end ) else: - message_body += _("
  • (All lines): %s - %s -> %s - %s
  • ") % ( - self.order_id.default_start_date, - self.order_id.default_end_date, - self.date_start, - self.date_end, - ) + message_body += _( + "
  • (All lines): %(default_start_date)s -" + "%(default_end_date)s" + "-> %(date_start)s - %(date_end)s
  • " + ) % { + "default_start_date": self.order_id.default_start_date, + "default_end_date": self.order_id.default_end_date, + "date_start": self.date_start, + "date_end": self.date_end, + } self.order_id.order_line.filtered( lambda x: x.start_date and x.end_date ).update_start_end_date(self.date_start, self.date_end) @@ -181,25 +173,32 @@ def action_confirm(self): if self.date_in_line: for line in self.line_ids: if self.from_line <= line.sequence <= self.to_line: - message_body += _("
  • %s: %s - %s -> %s - %s
  • ") % ( - line.order_line_id.product_id.name, - line.order_line_id.start_date, - line.order_line_id.end_date, - line.date_start, - line.date_end, - ) + message_body += _( + "
  • %(name)s: %(start_date)s - %(end_date)s->" + "%(date_start)s - %(date_end)s
  • " + ) % { + "name": line.order_line_id.product_id.name, + "start_date": line.order_line_id.start_date, + "end_date": line.order_line_id.end_date, + "date_start": line.date_start, + "date_end": line.date_end, + } line.order_line_id.update_start_end_date( line.date_start, line.date_end ) else: - message_body += _("
  • (Lines: %s - %s): %s - %s -> %s - %s
  • ") % ( - self.from_line, - self.to_line, - self.order_id.default_start_date, - self.order_id.default_end_date, - self.date_start, - self.date_end, - ) + message_body += _( + "
  • (Lines: %(from_line)s - %(to_line)s): " + "%(default_start_date)s - %(default_end_date)s " + "-> %(date_start)s - %(date_end)s
  • " + ) % { + "from_line": self.from_line, + "to_line": self.to_line, + "default_start_date": self.order_id.default_start_date, + "default_end_date": self.order_id.default_end_date, + "date_start": self.date_start, + "date_end": self.date_end, + } for line in self.line_ids: if self.from_line <= line.sequence <= self.to_line: line.order_line_id.update_start_end_date(