mirror of
https://github.com/OCA/manufacture.git
synced 2025-01-28 16:37:15 +02:00
[14.0][IMP] repair_stock_move: use standard reservation engine.
* Reserve moves in the same way it is done in other entities (pickings, MO's...). * Also give flexibility by alowing to easily force availability. * Other minor changes. * Set module as alpha.
This commit is contained in:
92
repair_stock_move/README.rst
Normal file
92
repair_stock_move/README.rst
Normal file
@@ -0,0 +1,92 @@
|
||||
=================
|
||||
Repair Stock Move
|
||||
=================
|
||||
|
||||
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png
|
||||
:target: https://odoo-community.org/page/development-status
|
||||
:alt: Alpha
|
||||
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png
|
||||
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
|
||||
:alt: License: LGPL-3
|
||||
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fmanufacture-lightgray.png?logo=github
|
||||
:target: https://github.com/OCA/manufacture/tree/14.0/repair_stock_move
|
||||
:alt: OCA/manufacture
|
||||
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
|
||||
:target: https://translation.odoo-community.org/projects/manufacture-14-0/manufacture-14-0-repair_stock_move
|
||||
:alt: Translate me on Weblate
|
||||
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
|
||||
:target: https://runbot.odoo-community.org/runbot/129/14.0
|
||||
:alt: Try me on Runbot
|
||||
|
||||
|badge1| |badge2| |badge3| |badge4| |badge5|
|
||||
|
||||
The purpose of this module is to modify the behaviour of the repair standard module. Achieving more flexibility in a repair process.
|
||||
|
||||
The first change that it applies is the modification of the creation of stock moves in the repair flow:
|
||||
|
||||
* Confirm Repair: creates draft stock moves on confirmation of the repair order.
|
||||
* Start Repair: confirms the stock moves.
|
||||
* End Repair: completes the stock moves and ends the repair order.
|
||||
|
||||
Another feature which this module includes is that it allows to add components during all the different stages of the repair process, which adjusts better to the needs of some businesses.
|
||||
|
||||
.. IMPORTANT::
|
||||
This is an alpha version, the data model and design can change at any time without warning.
|
||||
Only for development or testing purpose, do not use in production.
|
||||
`More details on development status <https://odoo-community.org/page/development-status>`_
|
||||
|
||||
**Table of contents**
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
Follow the Odoo standard repair module flow.
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/manufacture/issues>`_.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
||||
`feedback <https://github.com/OCA/manufacture/issues/new?body=module:%20repair_stock_move%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
||||
|
||||
Do not contact contributors directly about support or help with technical issues.
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Authors
|
||||
~~~~~~~
|
||||
|
||||
* ForgeFlow
|
||||
|
||||
Contributors
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* Mateu Griful <mateu.griful@forgeflow.com>
|
||||
* Lois Rilo <lois.rilo@forgeflow.com>
|
||||
|
||||
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/manufacture <https://github.com/OCA/manufacture/tree/14.0/repair_stock_move>`_ project on GitHub.
|
||||
|
||||
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
|
||||
@@ -1,5 +1 @@
|
||||
# Copyright (C) 2017-20 ForgeFlow S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from . import models
|
||||
from .hooks import post_load_hook
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
{
|
||||
"name": "Repair Stock Move",
|
||||
"version": "14.0.1.0.0",
|
||||
"development_status": "Alpha",
|
||||
"license": "LGPL-3",
|
||||
"category": "RMA",
|
||||
"category": "Repair",
|
||||
"summary": "Ongoing Repair Stock Moves Definition in odoo",
|
||||
"author": "ForgeFlow, Odoo Community Association (OCA)",
|
||||
"website": "https://github.com/OCA/manufacture",
|
||||
@@ -13,7 +14,6 @@
|
||||
"data": [
|
||||
"views/repair_order_views.xml",
|
||||
],
|
||||
"post_load": "post_load_hook",
|
||||
"installable": True,
|
||||
"application": False,
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Copyright 2021 ForgeFlow, S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from odoo.addons.repair.models.repair import Repair
|
||||
|
||||
|
||||
# flake8: noqa: C901
|
||||
def post_load_hook():
|
||||
def action_repair_end_new(self):
|
||||
self.write({"repaired": True})
|
||||
self.move_id._action_assign()
|
||||
self.move_id._action_done()
|
||||
for operation in self.operations:
|
||||
operation.move_id._action_assign()
|
||||
operation.move_id._action_done()
|
||||
vals = {"state": "done"}
|
||||
if not self.invoice_id and self.invoice_method == "after_repair":
|
||||
vals["state"] = "2binvoiced"
|
||||
self.write(vals)
|
||||
|
||||
if not hasattr(Repair, "action_repair_end_original"):
|
||||
Repair.action_repair_end_original = Repair.action_repair_end
|
||||
Repair.action_repair_end = action_repair_end_new
|
||||
@@ -24,6 +24,7 @@ class RepairLine(models.Model):
|
||||
"location_id": self.location_id.id,
|
||||
"location_dest_id": self.location_dest_id.id,
|
||||
"repair_id": self.repair_id.id,
|
||||
"repair_line_id": self.id,
|
||||
"origin": self.repair_id.name,
|
||||
"company_id": self.company_id.id,
|
||||
}
|
||||
@@ -35,16 +36,19 @@ class RepairLine(models.Model):
|
||||
res = super().create(vals)
|
||||
if res and res.repair_id.state == "confirmed":
|
||||
move = res.create_stock_move()
|
||||
move._action_confirm()
|
||||
res.move_id = move
|
||||
move._set_quantity_done(res.product_uom_qty)
|
||||
if res and res.repair_id.state == "under_repair":
|
||||
move = res.create_stock_move()
|
||||
move._action_confirm()
|
||||
move._set_quantity_done(res.product_uom_qty)
|
||||
move._action_assign()
|
||||
res.move_id = move
|
||||
return res
|
||||
|
||||
def unlink(self):
|
||||
for rec in self:
|
||||
rec.move_id.unlink()
|
||||
return super().unlink()
|
||||
@api.onchange("product_id")
|
||||
def _onchange_location(self):
|
||||
if self.state == "draft":
|
||||
self.location_id = self.repair_id.location_id
|
||||
|
||||
# TODO: write qty - update stock move.
|
||||
# TODO: default repair location in repair lines.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Copyright (C) 2021 ForgeFlow S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo import _, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tools import float_compare
|
||||
|
||||
|
||||
@@ -13,12 +13,14 @@ class RepairOrder(models.Model):
|
||||
comodel_name="stock.move",
|
||||
inverse_name="repair_id",
|
||||
)
|
||||
show_check_availability = fields.Boolean(
|
||||
compute="_compute_show_check_availability",
|
||||
help="Technical field used to compute whether the button "
|
||||
"'Check Availability' should be displayed.",
|
||||
)
|
||||
ignore_availability = fields.Boolean()
|
||||
# Make "Parts" editable in more states.
|
||||
operations = fields.One2many(
|
||||
comodel_name="repair.line",
|
||||
inverse_name="repair_id",
|
||||
string="Parts",
|
||||
copy=True,
|
||||
readonly=True,
|
||||
states={
|
||||
"draft": [("readonly", False)],
|
||||
"confirmed": [("readonly", False)],
|
||||
@@ -26,27 +28,7 @@ class RepairOrder(models.Model):
|
||||
"ready": [("readonly", False)],
|
||||
},
|
||||
)
|
||||
|
||||
product_qty = fields.Float(
|
||||
"Product Quantity",
|
||||
default=1.0,
|
||||
digits="Product Unit of Measure",
|
||||
readonly=True,
|
||||
required=True,
|
||||
states={
|
||||
"draft": [("readonly", False)],
|
||||
"confirmed": [("readonly", False)],
|
||||
"under_repair": [("readonly", False)],
|
||||
"ready": [("readonly", False)],
|
||||
},
|
||||
)
|
||||
|
||||
fees_lines = fields.One2many(
|
||||
comodel_name="repair.fee",
|
||||
inverse_name="repair_id",
|
||||
string="Operations",
|
||||
copy=True,
|
||||
readonly=True,
|
||||
states={
|
||||
"draft": [("readonly", False)],
|
||||
"confirmed": [("readonly", False)],
|
||||
@@ -55,40 +37,76 @@ class RepairOrder(models.Model):
|
||||
},
|
||||
)
|
||||
|
||||
def action_validate(self):
|
||||
res = super().action_validate()
|
||||
self._check_company()
|
||||
self.operations._check_company()
|
||||
self.fees_lines._check_company()
|
||||
res = {}
|
||||
precision = self.env["decimal.precision"].precision_get(
|
||||
"Product Unit of Measure"
|
||||
)
|
||||
Move = self.env["stock.move"]
|
||||
for repair in self:
|
||||
# Try to create move with the appropriate owner
|
||||
owner_id = False
|
||||
available_qty_owner = self.env["stock.quant"]._get_available_quantity(
|
||||
repair.product_id,
|
||||
repair.location_id,
|
||||
repair.lot_id,
|
||||
strict=True,
|
||||
@api.depends("state")
|
||||
def _compute_show_check_availability(self):
|
||||
for rec in self:
|
||||
rec.show_check_availability = (
|
||||
any(
|
||||
move.state in ("waiting", "confirmed", "partially_available")
|
||||
and float_compare(
|
||||
move.product_uom_qty,
|
||||
0,
|
||||
precision_rounding=move.product_uom.rounding,
|
||||
)
|
||||
for move in rec.stock_move_ids
|
||||
)
|
||||
and not rec.ignore_availability
|
||||
)
|
||||
if available_qty_owner <= 0.0:
|
||||
raise ValidationError(
|
||||
_("There is no stock of product: ") + repair.product_id.display_name
|
||||
)
|
||||
if (
|
||||
float_compare(
|
||||
available_qty_owner, repair.product_qty, precision_digits=precision
|
||||
)
|
||||
>= 0
|
||||
):
|
||||
owner_id = repair.partner_id.id
|
||||
|
||||
def _create_repair_stock_move(self):
|
||||
self.ensure_one()
|
||||
return self.env["stock.move"].create(
|
||||
{
|
||||
"name": self.name,
|
||||
"product_id": self.product_id.id,
|
||||
"product_uom": self.product_uom.id or self.product_id.uom_id.id,
|
||||
"product_uom_qty": self.product_qty,
|
||||
"partner_id": self.address_id.id,
|
||||
"location_id": self.location_id.id,
|
||||
"location_dest_id": self.location_id.id,
|
||||
"repair_id": self.id,
|
||||
"origin": self.name,
|
||||
"company_id": self.company_id.id,
|
||||
}
|
||||
)
|
||||
|
||||
def action_repair_confirm(self):
|
||||
res = super().action_repair_confirm()
|
||||
for repair in self:
|
||||
moves = self.env["stock.move"]
|
||||
for operation in repair.operations:
|
||||
move = operation.create_stock_move()
|
||||
moves |= move
|
||||
operation.write({"move_id": move.id})
|
||||
move = repair._create_repair_stock_move()
|
||||
repair.move_id = move
|
||||
self.mapped("stock_move_ids")._action_confirm()
|
||||
return res
|
||||
|
||||
def action_assign(self):
|
||||
self.filtered(lambda r: r.state == "draft").action_repair_start()
|
||||
moves = self.mapped("stock_move_ids")
|
||||
moves = moves.filtered(
|
||||
lambda move: move.state not in ("draft", "cancel", "done")
|
||||
)
|
||||
if not moves:
|
||||
raise UserError(_("Nothing to check the availability for."))
|
||||
moves._action_assign()
|
||||
return True
|
||||
|
||||
def action_repair_start(self):
|
||||
res = super().action_repair_start()
|
||||
self.mapped("stock_move_ids")._action_assign()
|
||||
return res
|
||||
|
||||
def action_force_availability(self):
|
||||
self.write({"ignore_availability": True})
|
||||
|
||||
def _force_qty_done_in_repair_lines(self):
|
||||
for operation in self.mapped("operations"):
|
||||
for move in operation.stock_move_ids:
|
||||
if move.state not in ["confirmed", "waiting", "partially_available"]:
|
||||
continue
|
||||
product_qty = move.product_uom._compute_quantity(
|
||||
operation.product_uom_qty,
|
||||
move.product_id.uom_id,
|
||||
@@ -101,69 +119,19 @@ class RepairOrder(models.Model):
|
||||
strict=False,
|
||||
)
|
||||
move._update_reserved_quantity(
|
||||
product_qty,
|
||||
product_qty - move.reserved_availability,
|
||||
available_quantity,
|
||||
move.location_id,
|
||||
lot_id=operation.lot_id,
|
||||
strict=False,
|
||||
)
|
||||
move._set_quantity_done(operation.product_uom_qty)
|
||||
|
||||
if operation.lot_id:
|
||||
move.move_line_ids.lot_id = operation.lot_id
|
||||
|
||||
moves |= move
|
||||
operation.write({"move_id": move.id, "state": "draft"})
|
||||
move = Move.create(
|
||||
{
|
||||
"name": repair.name,
|
||||
"product_id": repair.product_id.id,
|
||||
"product_uom": repair.product_uom.id or repair.product_id.uom_id.id,
|
||||
"product_uom_qty": repair.product_qty,
|
||||
"partner_id": repair.address_id.id,
|
||||
"location_id": repair.location_id.id,
|
||||
"location_dest_id": repair.location_id.id,
|
||||
"move_line_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": repair.product_id.id,
|
||||
"lot_id": repair.lot_id.id,
|
||||
"product_uom_qty": 0, # bypass reservation here
|
||||
"product_uom_id": repair.product_uom.id
|
||||
or repair.product_id.uom_id.id,
|
||||
"qty_done": repair.product_qty,
|
||||
"package_id": False,
|
||||
"result_package_id": False,
|
||||
"owner_id": owner_id,
|
||||
"location_id": repair.location_id.id, # TODO:ownerstuff
|
||||
"company_id": repair.company_id.id,
|
||||
"location_dest_id": repair.location_id.id,
|
||||
},
|
||||
)
|
||||
],
|
||||
"repair_id": repair.id,
|
||||
"origin": repair.name,
|
||||
"company_id": repair.company_id.id,
|
||||
}
|
||||
)
|
||||
consumed_lines = moves.mapped("move_line_ids")
|
||||
produced_lines = move.move_line_ids
|
||||
moves |= move
|
||||
produced_lines.write({"consume_line_ids": [(6, 0, consumed_lines.ids)]})
|
||||
res[repair.id] = move.id
|
||||
repair.move_id = move
|
||||
return res
|
||||
|
||||
def action_repair_start(self):
|
||||
super().action_repair_start()
|
||||
(self.move_id | self.operations.mapped("move_id"))._action_confirm()
|
||||
|
||||
def action_open_stock_moves(self):
|
||||
self.ensure_one()
|
||||
stock_move_ids = self.move_id.ids + self.operations.move_id.ids
|
||||
domain = [("id", "in", stock_move_ids)]
|
||||
domain = [("id", "in", self.mapped("stock_move_ids").ids)]
|
||||
action = {
|
||||
"name": _("Stock Moves"),
|
||||
"view_type": "tree",
|
||||
@@ -176,9 +144,33 @@ class RepairOrder(models.Model):
|
||||
return action
|
||||
|
||||
def action_repair_cancel(self):
|
||||
if self.move_id.state != "draft" or self.operations:
|
||||
raise ValidationError(
|
||||
_("Unable to cancel repair order due to already generated stock moves.")
|
||||
)
|
||||
else:
|
||||
super().action_repair_cancel()
|
||||
self.mapped("stock_move_ids")._action_cancel()
|
||||
return super().action_repair_cancel()
|
||||
|
||||
def action_repair_end(self):
|
||||
if any(r.show_check_availability for r in self):
|
||||
raise UserError(_("Some related stock moves are not available."))
|
||||
# I can not everything has been reserved.
|
||||
self._force_qty_done_in_repair_lines()
|
||||
for repair in self:
|
||||
operation_moves = repair.mapped("operations.move_id")
|
||||
if operation_moves:
|
||||
consumed_lines = operation_moves.mapped("move_line_ids")
|
||||
produced_lines = repair.move_id.move_line_ids
|
||||
operation_moves |= repair.move_id
|
||||
produced_lines.write({"consume_line_ids": [(6, 0, consumed_lines.ids)]})
|
||||
|
||||
self.move_id._set_quantity_done(self.move_id.product_uom_qty)
|
||||
self.move_id._action_done()
|
||||
for move in self.mapped("operations.move_id"):
|
||||
move._set_quantity_done(move.product_uom_qty)
|
||||
move._action_done()
|
||||
return super().action_repair_end()
|
||||
|
||||
def action_repair_done(self):
|
||||
self.ensure_one()
|
||||
if self.stock_move_ids:
|
||||
# With this module this should always be the case, so this is
|
||||
# effectively overriding the method.
|
||||
return {self.id: self.move_id.id}
|
||||
return super().action_repair_done()
|
||||
|
||||
@@ -10,4 +10,5 @@ class StockMove(models.Model):
|
||||
repair_line_id = fields.Many2one(
|
||||
comodel_name="repair.line",
|
||||
string="Repair Line",
|
||||
ondelete="cascade",
|
||||
)
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
* Mateu Griful <mateu.griful@forgeflow.com>
|
||||
* Lois Rilo <lois.rilo@forgeflow.com>
|
||||
@@ -1,9 +1,9 @@
|
||||
The purpose of this module is to modify the behaviour of the repair standard module. Achieving more flexibility in a repair process.
|
||||
|
||||
The first change that it applies is the modification of the creation of stock moves in the repair flow:
|
||||
|
||||
* Confirm Repair: creates draft stock moves on confirmation of the repair order.
|
||||
* Start Repair: confirms the stock moves.
|
||||
* End Repair: completes the stock moves and ends the repair order.
|
||||
|
||||
Another feature which this module includes is that it allows to add components during all the different stages of the repair process, which adjusts better to the needs of some businesses.
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
Follow the Odoo standard repair module flow.
|
||||
|
||||
438
repair_stock_move/static/description/index.html
Normal file
438
repair_stock_move/static/description/index.html
Normal file
@@ -0,0 +1,438 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils: http://docutils.sourceforge.net/" />
|
||||
<title>Repair Stock Move</title>
|
||||
<style type="text/css">
|
||||
|
||||
/*
|
||||
:Author: David Goodger (goodger@python.org)
|
||||
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
|
||||
:Copyright: This stylesheet has been placed in the public domain.
|
||||
|
||||
Default cascading style sheet for the HTML output of Docutils.
|
||||
|
||||
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
|
||||
customize this style sheet.
|
||||
*/
|
||||
|
||||
/* used to remove borders from tables and images */
|
||||
.borderless, table.borderless td, table.borderless th {
|
||||
border: 0 }
|
||||
|
||||
table.borderless td, table.borderless th {
|
||||
/* Override padding for "table.docutils td" with "! important".
|
||||
The right padding separates the table cells. */
|
||||
padding: 0 0.5em 0 0 ! important }
|
||||
|
||||
.first {
|
||||
/* Override more specific margin styles with "! important". */
|
||||
margin-top: 0 ! important }
|
||||
|
||||
.last, .with-subtitle {
|
||||
margin-bottom: 0 ! important }
|
||||
|
||||
.hidden {
|
||||
display: none }
|
||||
|
||||
.subscript {
|
||||
vertical-align: sub;
|
||||
font-size: smaller }
|
||||
|
||||
.superscript {
|
||||
vertical-align: super;
|
||||
font-size: smaller }
|
||||
|
||||
a.toc-backref {
|
||||
text-decoration: none ;
|
||||
color: black }
|
||||
|
||||
blockquote.epigraph {
|
||||
margin: 2em 5em ; }
|
||||
|
||||
dl.docutils dd {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Uncomment (and remove this text!) to get bold-faced definition list terms
|
||||
dl.docutils dt {
|
||||
font-weight: bold }
|
||||
*/
|
||||
|
||||
div.abstract {
|
||||
margin: 2em 5em }
|
||||
|
||||
div.abstract p.topic-title {
|
||||
font-weight: bold ;
|
||||
text-align: center }
|
||||
|
||||
div.admonition, div.attention, div.caution, div.danger, div.error,
|
||||
div.hint, div.important, div.note, div.tip, div.warning {
|
||||
margin: 2em ;
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.admonition p.admonition-title, div.hint p.admonition-title,
|
||||
div.important p.admonition-title, div.note p.admonition-title,
|
||||
div.tip p.admonition-title {
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
div.attention p.admonition-title, div.caution p.admonition-title,
|
||||
div.danger p.admonition-title, div.error p.admonition-title,
|
||||
div.warning p.admonition-title, .code .error {
|
||||
color: red ;
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
/* Uncomment (and remove this text!) to get reduced vertical space in
|
||||
compound paragraphs.
|
||||
div.compound .compound-first, div.compound .compound-middle {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
div.compound .compound-last, div.compound .compound-middle {
|
||||
margin-top: 0.5em }
|
||||
*/
|
||||
|
||||
div.dedication {
|
||||
margin: 2em 5em ;
|
||||
text-align: center ;
|
||||
font-style: italic }
|
||||
|
||||
div.dedication p.topic-title {
|
||||
font-weight: bold ;
|
||||
font-style: normal }
|
||||
|
||||
div.figure {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
div.footer, div.header {
|
||||
clear: both;
|
||||
font-size: smaller }
|
||||
|
||||
div.line-block {
|
||||
display: block ;
|
||||
margin-top: 1em ;
|
||||
margin-bottom: 1em }
|
||||
|
||||
div.line-block div.line-block {
|
||||
margin-top: 0 ;
|
||||
margin-bottom: 0 ;
|
||||
margin-left: 1.5em }
|
||||
|
||||
div.sidebar {
|
||||
margin: 0 0 0.5em 1em ;
|
||||
border: medium outset ;
|
||||
padding: 1em ;
|
||||
background-color: #ffffee ;
|
||||
width: 40% ;
|
||||
float: right ;
|
||||
clear: right }
|
||||
|
||||
div.sidebar p.rubric {
|
||||
font-family: sans-serif ;
|
||||
font-size: medium }
|
||||
|
||||
div.system-messages {
|
||||
margin: 5em }
|
||||
|
||||
div.system-messages h1 {
|
||||
color: red }
|
||||
|
||||
div.system-message {
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.system-message p.system-message-title {
|
||||
color: red ;
|
||||
font-weight: bold }
|
||||
|
||||
div.topic {
|
||||
margin: 2em }
|
||||
|
||||
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
|
||||
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
|
||||
margin-top: 0.4em }
|
||||
|
||||
h1.title {
|
||||
text-align: center }
|
||||
|
||||
h2.subtitle {
|
||||
text-align: center }
|
||||
|
||||
hr.docutils {
|
||||
width: 75% }
|
||||
|
||||
img.align-left, .figure.align-left, object.align-left, table.align-left {
|
||||
clear: left ;
|
||||
float: left ;
|
||||
margin-right: 1em }
|
||||
|
||||
img.align-right, .figure.align-right, object.align-right, table.align-right {
|
||||
clear: right ;
|
||||
float: right ;
|
||||
margin-left: 1em }
|
||||
|
||||
img.align-center, .figure.align-center, object.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.align-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left }
|
||||
|
||||
.align-center {
|
||||
clear: both ;
|
||||
text-align: center }
|
||||
|
||||
.align-right {
|
||||
text-align: right }
|
||||
|
||||
/* reset inner alignment in figures */
|
||||
div.align-right {
|
||||
text-align: inherit }
|
||||
|
||||
/* div.align-center * { */
|
||||
/* text-align: left } */
|
||||
|
||||
.align-top {
|
||||
vertical-align: top }
|
||||
|
||||
.align-middle {
|
||||
vertical-align: middle }
|
||||
|
||||
.align-bottom {
|
||||
vertical-align: bottom }
|
||||
|
||||
ol.simple, ul.simple {
|
||||
margin-bottom: 1em }
|
||||
|
||||
ol.arabic {
|
||||
list-style: decimal }
|
||||
|
||||
ol.loweralpha {
|
||||
list-style: lower-alpha }
|
||||
|
||||
ol.upperalpha {
|
||||
list-style: upper-alpha }
|
||||
|
||||
ol.lowerroman {
|
||||
list-style: lower-roman }
|
||||
|
||||
ol.upperroman {
|
||||
list-style: upper-roman }
|
||||
|
||||
p.attribution {
|
||||
text-align: right ;
|
||||
margin-left: 50% }
|
||||
|
||||
p.caption {
|
||||
font-style: italic }
|
||||
|
||||
p.credits {
|
||||
font-style: italic ;
|
||||
font-size: smaller }
|
||||
|
||||
p.label {
|
||||
white-space: nowrap }
|
||||
|
||||
p.rubric {
|
||||
font-weight: bold ;
|
||||
font-size: larger ;
|
||||
color: maroon ;
|
||||
text-align: center }
|
||||
|
||||
p.sidebar-title {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold ;
|
||||
font-size: larger }
|
||||
|
||||
p.sidebar-subtitle {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
p.topic-title {
|
||||
font-weight: bold }
|
||||
|
||||
pre.address {
|
||||
margin-bottom: 0 ;
|
||||
margin-top: 0 ;
|
||||
font: inherit }
|
||||
|
||||
pre.literal-block, pre.doctest-block, pre.math, pre.code {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
pre.code .ln { color: grey; } /* line numbers */
|
||||
pre.code, code { background-color: #eeeeee }
|
||||
pre.code .comment, code .comment { color: #5C6576 }
|
||||
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
|
||||
pre.code .literal.string, code .literal.string { color: #0C5404 }
|
||||
pre.code .name.builtin, code .name.builtin { color: #352B84 }
|
||||
pre.code .deleted, code .deleted { background-color: #DEB0A1}
|
||||
pre.code .inserted, code .inserted { background-color: #A3D289}
|
||||
|
||||
span.classifier {
|
||||
font-family: sans-serif ;
|
||||
font-style: oblique }
|
||||
|
||||
span.classifier-delimiter {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
span.interpreted {
|
||||
font-family: sans-serif }
|
||||
|
||||
span.option {
|
||||
white-space: nowrap }
|
||||
|
||||
span.pre {
|
||||
white-space: pre }
|
||||
|
||||
span.problematic {
|
||||
color: red }
|
||||
|
||||
span.section-subtitle {
|
||||
/* font-size relative to parent (h1..h6 element) */
|
||||
font-size: 80% }
|
||||
|
||||
table.citation {
|
||||
border-left: solid 1px gray;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docinfo {
|
||||
margin: 2em 4em }
|
||||
|
||||
table.docutils {
|
||||
margin-top: 0.5em ;
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
table.footnote {
|
||||
border-left: solid 1px black;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docutils td, table.docutils th,
|
||||
table.docinfo td, table.docinfo th {
|
||||
padding-left: 0.5em ;
|
||||
padding-right: 0.5em ;
|
||||
vertical-align: top }
|
||||
|
||||
table.docutils th.field-name, table.docinfo th.docinfo-name {
|
||||
font-weight: bold ;
|
||||
text-align: left ;
|
||||
white-space: nowrap ;
|
||||
padding-left: 0 }
|
||||
|
||||
/* "booktabs" style (no vertical lines) */
|
||||
table.docutils.booktabs {
|
||||
border: 0px;
|
||||
border-top: 2px solid;
|
||||
border-bottom: 2px solid;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table.docutils.booktabs * {
|
||||
border: 0px;
|
||||
}
|
||||
table.docutils.booktabs th {
|
||||
border-bottom: thin solid;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
|
||||
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
|
||||
font-size: 100% }
|
||||
|
||||
ul.auto-toc {
|
||||
list-style-type: none }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="repair-stock-move">
|
||||
<h1 class="title">Repair Stock Move</h1>
|
||||
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Alpha" src="https://img.shields.io/badge/maturity-Alpha-red.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/lgpl-3.0-standalone.html"><img alt="License: LGPL-3" src="https://img.shields.io/badge/licence-LGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/manufacture/tree/14.0/repair_stock_move"><img alt="OCA/manufacture" src="https://img.shields.io/badge/github-OCA%2Fmanufacture-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/manufacture-14-0/manufacture-14-0-repair_stock_move"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/129/14.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
|
||||
<p>The purpose of this module is to modify the behaviour of the repair standard module. Achieving more flexibility in a repair process.</p>
|
||||
<p>The first change that it applies is the modification of the creation of stock moves in the repair flow:</p>
|
||||
<ul class="simple">
|
||||
<li>Confirm Repair: creates draft stock moves on confirmation of the repair order.</li>
|
||||
<li>Start Repair: confirms the stock moves.</li>
|
||||
<li>End Repair: completes the stock moves and ends the repair order.</li>
|
||||
</ul>
|
||||
<p>Another feature which this module includes is that it allows to add components during all the different stages of the repair process, which adjusts better to the needs of some businesses.</p>
|
||||
<div class="admonition important">
|
||||
<p class="first admonition-title">Important</p>
|
||||
<p class="last">This is an alpha version, the data model and design can change at any time without warning.
|
||||
Only for development or testing purpose, do not use in production.
|
||||
<a class="reference external" href="https://odoo-community.org/page/development-status">More details on development status</a></p>
|
||||
</div>
|
||||
<p><strong>Table of contents</strong></p>
|
||||
<div class="contents local topic" id="contents">
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#usage" id="id1">Usage</a></li>
|
||||
<li><a class="reference internal" href="#bug-tracker" id="id2">Bug Tracker</a></li>
|
||||
<li><a class="reference internal" href="#credits" id="id3">Credits</a><ul>
|
||||
<li><a class="reference internal" href="#authors" id="id4">Authors</a></li>
|
||||
<li><a class="reference internal" href="#contributors" id="id5">Contributors</a></li>
|
||||
<li><a class="reference internal" href="#maintainers" id="id6">Maintainers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="usage">
|
||||
<h1><a class="toc-backref" href="#id1">Usage</a></h1>
|
||||
<p>Follow the Odoo standard repair module flow.</p>
|
||||
</div>
|
||||
<div class="section" id="bug-tracker">
|
||||
<h1><a class="toc-backref" href="#id2">Bug Tracker</a></h1>
|
||||
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/manufacture/issues">GitHub Issues</a>.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
||||
<a class="reference external" href="https://github.com/OCA/manufacture/issues/new?body=module:%20repair_stock_move%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
|
||||
<p>Do not contact contributors directly about support or help with technical issues.</p>
|
||||
</div>
|
||||
<div class="section" id="credits">
|
||||
<h1><a class="toc-backref" href="#id3">Credits</a></h1>
|
||||
<div class="section" id="authors">
|
||||
<h2><a class="toc-backref" href="#id4">Authors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>ForgeFlow</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="contributors">
|
||||
<h2><a class="toc-backref" href="#id5">Contributors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Mateu Griful <<a class="reference external" href="mailto:mateu.griful@forgeflow.com">mateu.griful@forgeflow.com</a>></li>
|
||||
<li>Lois Rilo <<a class="reference external" href="mailto:lois.rilo@forgeflow.com">lois.rilo@forgeflow.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="maintainers">
|
||||
<h2><a class="toc-backref" href="#id6">Maintainers</a></h2>
|
||||
<p>This module is maintained by the OCA.</p>
|
||||
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
|
||||
<p>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.</p>
|
||||
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/manufacture/tree/14.0/repair_stock_move">OCA/manufacture</a> project on GitHub.</p>
|
||||
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -55,6 +55,7 @@ class TestRepairStockMove(common.SavepointCase):
|
||||
)
|
||||
|
||||
# Repair Orders
|
||||
dest_loc_id = cls.product_1.property_stock_production.id
|
||||
cls.repair1 = cls.env["repair.order"].create(
|
||||
{
|
||||
"address_id": cls.res_partner_address_1.id,
|
||||
@@ -70,9 +71,9 @@ class TestRepairStockMove(common.SavepointCase):
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"location_dest_id": cls.product_1.property_stock_production.id,
|
||||
"location_dest_id": dest_loc_id,
|
||||
"location_id": cls.stock_location_14.id,
|
||||
"name": cls.product_1.get_product_multiline_description_sale(),
|
||||
"name": cls.product_1.display_name,
|
||||
"product_id": cls.product_2.id,
|
||||
"product_uom": cls.env.ref("uom.product_uom_unit").id,
|
||||
"product_uom_qty": 1.0,
|
||||
@@ -88,7 +89,7 @@ class TestRepairStockMove(common.SavepointCase):
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"name": cls.service.get_product_multiline_description_sale(),
|
||||
"name": cls.service.display_name,
|
||||
"product_id": cls.service.id,
|
||||
"product_uom_qty": 1.0,
|
||||
"product_uom": cls.env.ref("uom.product_uom_unit").id,
|
||||
@@ -106,19 +107,6 @@ class TestRepairStockMove(common.SavepointCase):
|
||||
def test_stock_move_state(self):
|
||||
# Validate Repair Order
|
||||
self.repair1.action_validate()
|
||||
self.assertEqual(
|
||||
self.repair1.move_id.state,
|
||||
"draft",
|
||||
"Generated stock move state should be draft",
|
||||
)
|
||||
for operation in self.repair1.operations:
|
||||
self.assertEqual(
|
||||
operation.move_id.state,
|
||||
"draft",
|
||||
"Generated stock move state should be draft",
|
||||
)
|
||||
# Start Repair
|
||||
self.repair1.action_repair_start()
|
||||
self.assertEqual(
|
||||
self.repair1.move_id.state,
|
||||
"confirmed",
|
||||
@@ -130,6 +118,8 @@ class TestRepairStockMove(common.SavepointCase):
|
||||
"confirmed",
|
||||
"Generated stock move state should be confirmed",
|
||||
)
|
||||
# Start Repair
|
||||
self.repair1.action_repair_start()
|
||||
# End Repair
|
||||
self.repair1.action_repair_end()
|
||||
self.assertEqual(
|
||||
|
||||
@@ -6,8 +6,26 @@
|
||||
<field name="model">repair.order</field>
|
||||
<field name="inherit_id" ref="repair.view_repair_order_form" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="product_qty" position="replace">
|
||||
<field name="product_qty" />
|
||||
<header position="inside">
|
||||
<button
|
||||
name="action_assign"
|
||||
attrs="{'invisible': [('show_check_availability', '=', False)]}"
|
||||
string="Check Availability"
|
||||
type="object"
|
||||
class="oe_highlight"
|
||||
groups="base.group_user"
|
||||
/>
|
||||
<button
|
||||
name="action_force_availability"
|
||||
attrs="{'invisible': [('show_check_availability', '=', False)]}"
|
||||
string="Force Availability"
|
||||
type="object"
|
||||
groups="base.group_user"
|
||||
/>
|
||||
<field name="show_check_availability" invisible="1" />
|
||||
</header>
|
||||
<field name="product_qty" position="attributes">
|
||||
<attribute name="attrs" />
|
||||
</field>
|
||||
<xpath expr="//div[hasclass('oe_button_box')]" position="inside">
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user