mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
[MIG] stock_request_kanban: Migration to 13.0
This commit is contained in:
committed by
Bernat Puig Font
parent
918801ec94
commit
6c8a1894b1
@@ -2,30 +2,27 @@
|
|||||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
{
|
{
|
||||||
'name': 'Stock Request kanban',
|
"name": "Stock Request kanban",
|
||||||
'version': '12.0.1.0.1',
|
"version": "13.0.1.0.1",
|
||||||
'category': 'Reporting',
|
"category": "Warehouse Management",
|
||||||
'website': 'https://github.com/OCA/stock-logistics-warehouse',
|
"website": "https://github.com/OCA/stock-logistics-warehouse",
|
||||||
'author': 'Creu Blanca, Eficent, Odoo Community Association (OCA)',
|
"author": "Creu Blanca, ForgeFlow, Odoo Community Association (OCA)",
|
||||||
'license': 'AGPL-3',
|
"license": "LGPL-3",
|
||||||
'summary': 'Adds a stock request order, and takes stock requests as lines',
|
"summary": "Adds a stock request order, and takes stock requests as lines",
|
||||||
'depends': [
|
"depends": ["stock_request", "barcodes"],
|
||||||
'stock_request',
|
"data": [
|
||||||
'barcodes',
|
"data/stock_request_sequence_data.xml",
|
||||||
|
"report/report_paper_format.xml",
|
||||||
|
"wizard/wizard_stock_inventory_kanban_views.xml",
|
||||||
|
"wizard/wizard_stock_request_kanban_views.xml",
|
||||||
|
"wizard/wizard_stock_request_order_kanban_views.xml",
|
||||||
|
"views/stock_request_order_views.xml",
|
||||||
|
"views/stock_request_kanban_views.xml",
|
||||||
|
"views/stock_inventory_kanban_views.xml",
|
||||||
|
"views/stock_request_menu.xml",
|
||||||
|
"report/stock_request_kanban_templates.xml",
|
||||||
|
"security/ir.model.access.csv",
|
||||||
],
|
],
|
||||||
'data': [
|
"installable": True,
|
||||||
'data/stock_request_sequence_data.xml',
|
"application": False,
|
||||||
'report/report_paper_format.xml',
|
|
||||||
'wizard/wizard_stock_inventory_kanban_views.xml',
|
|
||||||
'wizard/wizard_stock_request_kanban_views.xml',
|
|
||||||
'wizard/wizard_stock_request_order_kanban_views.xml',
|
|
||||||
'views/stock_request_order_views.xml',
|
|
||||||
'views/stock_request_kanban_views.xml',
|
|
||||||
'views/stock_inventory_kanban_views.xml',
|
|
||||||
'views/stock_request_menu.xml',
|
|
||||||
'report/stock_request_kanban_templates.xml',
|
|
||||||
'security/ir.model.access.csv',
|
|
||||||
],
|
|
||||||
'installable': True,
|
|
||||||
'application': False,
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,19 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
<data noupdate="1">
|
<data noupdate="1">
|
||||||
|
|
||||||
<record id="seq_stock_request_kanban" model="ir.sequence">
|
<record id="seq_stock_request_kanban" model="ir.sequence">
|
||||||
<field name="name">Stock Request Kanban</field>
|
<field name="name">Stock Request Kanban</field>
|
||||||
<field name="code">stock.request.kanban</field>
|
<field name="code">stock.request.kanban</field>
|
||||||
<field name="prefix">KB</field>
|
<field name="prefix">KB</field>
|
||||||
<field name="padding">5</field>
|
<field name="padding">5</field>
|
||||||
<field name="company_id" eval="False"/>
|
<field name="company_id" eval="False" />
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="seq_stock_inventory_kanban" model="ir.sequence">
|
<record id="seq_stock_inventory_kanban" model="ir.sequence">
|
||||||
<field name="name">Stock Inventory Kanban</field>
|
<field name="name">Stock Inventory Kanban</field>
|
||||||
<field name="code">stock.inventory.kanban</field>
|
<field name="code">stock.inventory.kanban</field>
|
||||||
<field name="prefix">IKB</field>
|
<field name="prefix">IKB</field>
|
||||||
<field name="padding">5</field>
|
<field name="padding">5</field>
|
||||||
<field name="company_id" eval="False"/>
|
<field name="company_id" eval="False" />
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -1,69 +1,76 @@
|
|||||||
# Copyright 2018 Creu Blanca
|
# Copyright 2018 Creu Blanca
|
||||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
from odoo import api, models, fields
|
from odoo import api, fields, models
|
||||||
from odoo.osv import expression
|
from odoo.osv import expression
|
||||||
|
|
||||||
|
|
||||||
class StockInventoryKanban(models.Model):
|
class StockInventoryKanban(models.Model):
|
||||||
_name = 'stock.inventory.kanban'
|
_name = "stock.inventory.kanban"
|
||||||
_description = 'Inventory for Kanban'
|
_description = "Inventory for Kanban"
|
||||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
_inherit = ["mail.thread", "mail.activity.mixin"]
|
||||||
|
|
||||||
name = fields.Char(
|
name = fields.Char(
|
||||||
readonly=True, states={'draft': [('readonly', False)]}, copy=False,
|
readonly=True, states={"draft": [("readonly", False)]}, copy=False
|
||||||
)
|
)
|
||||||
state = fields.Selection(
|
state = fields.Selection(
|
||||||
[
|
[
|
||||||
('draft', 'Draft'),
|
("draft", "Draft"),
|
||||||
('in_progress', 'In progress'),
|
("in_progress", "In progress"),
|
||||||
('finished', 'Finished'),
|
("finished", "Finished"),
|
||||||
('closed', 'Closed'),
|
("closed", "Closed"),
|
||||||
('cancelled', 'Cancelled')
|
("cancelled", "Cancelled"),
|
||||||
],
|
],
|
||||||
required=True, default='draft', readonly=True, copy=False,
|
required=True,
|
||||||
track_visibility='onchange'
|
default="draft",
|
||||||
|
readonly=True,
|
||||||
|
copy=False,
|
||||||
|
track_visibility="onchange",
|
||||||
)
|
)
|
||||||
warehouse_ids = fields.Many2many(
|
warehouse_ids = fields.Many2many(
|
||||||
'stock.warehouse', string='Warehouse',
|
"stock.warehouse",
|
||||||
|
string="Warehouse",
|
||||||
ondelete="cascade",
|
ondelete="cascade",
|
||||||
readonly=True, states={'draft': [('readonly', False)]},
|
readonly=True,
|
||||||
|
states={"draft": [("readonly", False)]},
|
||||||
)
|
)
|
||||||
location_ids = fields.Many2many(
|
location_ids = fields.Many2many(
|
||||||
'stock.location', string='Location',
|
"stock.location",
|
||||||
domain=[('usage', 'in', ['internal', 'transit'])],
|
string="Location",
|
||||||
|
domain=[("usage", "in", ["internal", "transit"])],
|
||||||
ondelete="cascade",
|
ondelete="cascade",
|
||||||
readonly=True, states={'draft': [('readonly', False)]},
|
readonly=True,
|
||||||
|
states={"draft": [("readonly", False)]},
|
||||||
)
|
)
|
||||||
product_ids = fields.Many2many(
|
product_ids = fields.Many2many(
|
||||||
'product.product', string='Products',
|
"product.product",
|
||||||
domain=[('type', 'in', ['product', 'consu'])],
|
string="Products",
|
||||||
ondelete='cascade',
|
domain=[("type", "in", ["product", "consu"])],
|
||||||
readonly=True, states={'draft': [('readonly', False)]},
|
ondelete="cascade",
|
||||||
|
readonly=True,
|
||||||
|
states={"draft": [("readonly", False)]},
|
||||||
)
|
)
|
||||||
kanban_ids = fields.Many2many(
|
kanban_ids = fields.Many2many(
|
||||||
'stock.request.kanban',
|
"stock.request.kanban",
|
||||||
relation='stock_inventory_kanban_kanban',
|
relation="stock_inventory_kanban_kanban",
|
||||||
readonly=True, copy=False,
|
readonly=True,
|
||||||
|
copy=False,
|
||||||
)
|
)
|
||||||
scanned_kanban_ids = fields.Many2many(
|
scanned_kanban_ids = fields.Many2many(
|
||||||
'stock.request.kanban',
|
"stock.request.kanban",
|
||||||
relation='stock_inventory_kanban_scanned_kanban',
|
relation="stock_inventory_kanban_scanned_kanban",
|
||||||
readonly=True, copy=False,
|
readonly=True,
|
||||||
|
copy=False,
|
||||||
)
|
)
|
||||||
missing_kanban_ids = fields.Many2many(
|
missing_kanban_ids = fields.Many2many(
|
||||||
'stock.request.kanban',
|
"stock.request.kanban", readonly=True, compute="_compute_missing_kanban"
|
||||||
readonly=True,
|
|
||||||
compute='_compute_missing_kanban'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
count_missing_kanbans = fields.Integer(
|
count_missing_kanbans = fields.Integer(
|
||||||
'Missing Kanbans',
|
"Missing Kanbans", readonly=True, compute="_compute_missing_kanban"
|
||||||
readonly=True,
|
|
||||||
compute='_compute_missing_kanban',
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@api.depends('kanban_ids', 'scanned_kanban_ids')
|
@api.depends("kanban_ids", "scanned_kanban_ids")
|
||||||
def _compute_missing_kanban(self):
|
def _compute_missing_kanban(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
rec.missing_kanban_ids = rec.kanban_ids.filtered(
|
rec.missing_kanban_ids = rec.kanban_ids.filtered(
|
||||||
@@ -74,88 +81,73 @@ class StockInventoryKanban(models.Model):
|
|||||||
def _get_inventory_kanban_domain(self):
|
def _get_inventory_kanban_domain(self):
|
||||||
domain = []
|
domain = []
|
||||||
if self.warehouse_ids:
|
if self.warehouse_ids:
|
||||||
domain = expression.AND((
|
domain = expression.AND(
|
||||||
domain, [('warehouse_id', 'in', self.warehouse_ids.ids)]
|
(domain, [("warehouse_id", "in", self.warehouse_ids.ids)])
|
||||||
))
|
)
|
||||||
if self.product_ids:
|
if self.product_ids:
|
||||||
domain = expression.AND((
|
domain = expression.AND(
|
||||||
domain, [('product_id', 'in', self.product_ids.ids)]
|
(domain, [("product_id", "in", self.product_ids.ids)])
|
||||||
))
|
)
|
||||||
if self.location_ids:
|
if self.location_ids:
|
||||||
domain = expression.AND((
|
domain = expression.AND(
|
||||||
domain, [('location_id', 'in', self.location_ids.ids)]
|
(domain, [("location_id", "in", self.location_ids.ids)])
|
||||||
))
|
)
|
||||||
return domain
|
return domain
|
||||||
|
|
||||||
def _start_inventory_values(self):
|
def _start_inventory_values(self):
|
||||||
return {
|
return {"state": "in_progress"}
|
||||||
'state': 'in_progress'
|
|
||||||
}
|
|
||||||
|
|
||||||
def _finish_inventory_values(self):
|
def _finish_inventory_values(self):
|
||||||
return {
|
return {"state": "finished"}
|
||||||
'state': 'finished'
|
|
||||||
}
|
|
||||||
|
|
||||||
def _close_inventory_values(self):
|
def _close_inventory_values(self):
|
||||||
return {
|
return {"state": "closed"}
|
||||||
'state': 'closed'
|
|
||||||
}
|
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def create(self, vals):
|
def create(self, vals):
|
||||||
if vals.get('name', '/') == '/':
|
if vals.get("name", "/") == "/":
|
||||||
vals['name'] = self.env['ir.sequence'].next_by_code(
|
vals["name"] = self.env["ir.sequence"].next_by_code(
|
||||||
'stock.inventory.kanban')
|
"stock.inventory.kanban"
|
||||||
|
)
|
||||||
return super().create(vals)
|
return super().create(vals)
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def calculate_kanbans(self):
|
def calculate_kanbans(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
if rec.state == 'draft':
|
if rec.state == "draft":
|
||||||
rec.kanban_ids = self.env['stock.request.kanban'].search(
|
rec.kanban_ids = self.env["stock.request.kanban"].search(
|
||||||
rec._get_inventory_kanban_domain()
|
rec._get_inventory_kanban_domain()
|
||||||
)
|
)
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def start_inventory(self):
|
def start_inventory(self):
|
||||||
self.calculate_kanbans()
|
self.calculate_kanbans()
|
||||||
self.write(self._start_inventory_values())
|
self.write(self._start_inventory_values())
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def finish_inventory(self):
|
def finish_inventory(self):
|
||||||
self.write(self._finish_inventory_values())
|
self.write(self._finish_inventory_values())
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def close_inventory(self):
|
def close_inventory(self):
|
||||||
self.write(self._close_inventory_values())
|
self.write(self._close_inventory_values())
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def print_missing_kanbans(self):
|
def print_missing_kanbans(self):
|
||||||
""" Print the missing kanban cards in order to restore them
|
""" Print the missing kanban cards in order to restore them
|
||||||
"""
|
"""
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
return self.env.ref(
|
return self.env.ref("stock_request_kanban.action_report_kanban").report_action(
|
||||||
'stock_request_kanban.action_report_kanban').report_action(
|
|
||||||
self.missing_kanban_ids
|
self.missing_kanban_ids
|
||||||
)
|
)
|
||||||
|
|
||||||
def _cancel_inventory_values(self):
|
def _cancel_inventory_values(self):
|
||||||
return {
|
return {"state": "cancelled"}
|
||||||
'state': 'cancelled',
|
|
||||||
}
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def cancel(self):
|
def cancel(self):
|
||||||
self.write(self._cancel_inventory_values())
|
self.write(self._cancel_inventory_values())
|
||||||
|
|
||||||
def _to_draft_inventory_values(self):
|
def _to_draft_inventory_values(self):
|
||||||
return {
|
return {
|
||||||
'state': 'draft',
|
"state": "draft",
|
||||||
'kanban_ids': [(5, 0)],
|
"kanban_ids": [(5, 0)],
|
||||||
'scanned_kanban_ids': [(5, 0)],
|
"scanned_kanban_ids": [(5, 0)],
|
||||||
}
|
}
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def to_draft(self):
|
def to_draft(self):
|
||||||
self.write(self._to_draft_inventory_values())
|
self.write(self._to_draft_inventory_values())
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
# Copyright 2018 Creu Blanca
|
# Copyright 2018 Creu Blanca
|
||||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
from odoo import models, fields
|
from odoo import fields, models
|
||||||
|
|
||||||
|
|
||||||
class StockRequest(models.Model):
|
class StockRequest(models.Model):
|
||||||
_inherit = 'stock.request'
|
_inherit = "stock.request"
|
||||||
|
|
||||||
kanban_id = fields.Many2one('stock.request.kanban', readonly=True)
|
kanban_id = fields.Many2one("stock.request.kanban", readonly=True)
|
||||||
|
|||||||
@@ -1,47 +1,52 @@
|
|||||||
# Copyright 2018 Creu Blanca
|
# Copyright 2018 Creu Blanca
|
||||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
from odoo import api, models, fields, _
|
|
||||||
from odoo.exceptions import ValidationError
|
|
||||||
from reportlab.graphics.barcode import getCodes
|
from reportlab.graphics.barcode import getCodes
|
||||||
|
|
||||||
|
from odoo import _, api, fields, models
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
|
|
||||||
class StockRequestKanban(models.Model):
|
class StockRequestKanban(models.Model):
|
||||||
_name = 'stock.request.kanban'
|
_name = "stock.request.kanban"
|
||||||
_description = 'Stock Request Kanban'
|
_description = "Stock Request Kanban"
|
||||||
_inherit = 'stock.request.abstract'
|
_inherit = "stock.request.abstract"
|
||||||
|
|
||||||
active = fields.Boolean(default=True)
|
active = fields.Boolean(default=True)
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def create(self, vals):
|
def create(self, vals):
|
||||||
if vals.get('name', '/') == '/':
|
if vals.get("name", "/") == "/":
|
||||||
vals['name'] = self.env['ir.sequence'].next_by_code(
|
vals["name"] = self.env["ir.sequence"].next_by_code("stock.request.kanban")
|
||||||
'stock.request.kanban')
|
|
||||||
return super().create(vals)
|
return super().create(vals)
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def get_barcode_format(self):
|
def get_barcode_format(self):
|
||||||
return self.env['ir.config_parameter'].sudo().get_param(
|
return (
|
||||||
'stock_request_kanban.barcode_format', default='Standard39'
|
self.env["ir.config_parameter"]
|
||||||
|
.sudo()
|
||||||
|
.get_param("stock_request_kanban.barcode_format", default="Standard39")
|
||||||
)
|
)
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _recompute_barcode(self, barcode):
|
def _recompute_barcode(self, barcode):
|
||||||
if self.env['ir.config_parameter'].sudo().get_param(
|
if (
|
||||||
'stock_request_kanban.crc', default='1'
|
self.env["ir.config_parameter"]
|
||||||
) == '0':
|
.sudo()
|
||||||
|
.get_param("stock_request_kanban.crc", default="1")
|
||||||
|
== "0"
|
||||||
|
):
|
||||||
return barcode
|
return barcode
|
||||||
bcc = getCodes()[self.get_barcode_format()](value=barcode[:-1])
|
bcc = getCodes()[self.get_barcode_format()](value=barcode[:-1])
|
||||||
bcc.validate()
|
bcc.validate()
|
||||||
bcc.encode()
|
bcc.encode()
|
||||||
if bcc.encoded[1:-1] != barcode:
|
if bcc.encoded[1:-1] != barcode:
|
||||||
raise ValidationError(_('CRC is not valid'))
|
raise ValidationError(_("CRC is not valid"))
|
||||||
return barcode[:-1]
|
return barcode[:-1]
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def search_barcode(self, barcode):
|
def search_barcode(self, barcode):
|
||||||
recomputed_barcode = self._recompute_barcode(barcode)
|
recomputed_barcode = self._recompute_barcode(barcode)
|
||||||
return self.env['stock.request.kanban'].search([
|
return self.env["stock.request.kanban"].search(
|
||||||
('name', '=', recomputed_barcode)
|
[("name", "ilike", recomputed_barcode)]
|
||||||
])
|
)
|
||||||
|
|||||||
@@ -11,5 +11,4 @@
|
|||||||
<field name="header_spacing">0</field>
|
<field name="header_spacing">0</field>
|
||||||
<field name="dpi">72</field>
|
<field name="dpi">72</field>
|
||||||
</record>
|
</record>
|
||||||
|
</odoo>
|
||||||
</odoo>
|
|
||||||
|
|||||||
@@ -1,90 +1,103 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<!-- Copyright 2017 Eficent
|
<!-- Copyright 2017-2020 ForgeFlow, S.L.
|
||||||
License LGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
|
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). -->
|
||||||
<odoo>
|
<odoo>
|
||||||
<template id="report_simple_label">
|
<template id="report_simple_label">
|
||||||
<div class="col-xs-3" style="padding:20;height:350px;">
|
<div class="col-3" style="padding:20;height:350px;">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12"
|
<div
|
||||||
style="height:15%;border:2px solid black;text-align:center;vertical-align:middle;display:table;">
|
class="col-12"
|
||||||
|
style="height:15%;border:2px solid black;text-align:center;vertical-align:middle;display:table;"
|
||||||
|
>
|
||||||
<div style="display: table-cell; vertical-align: middle;">
|
<div style="display: table-cell; vertical-align: middle;">
|
||||||
<strong t-field="o.location_id.name"/>
|
<strong t-field="o.location_id.name" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row"
|
<div class="row" t-if="o.product_id.default_code">
|
||||||
t-if="o.product_id.default_code">
|
<div
|
||||||
<div class="col-xs-12"
|
class="col-12"
|
||||||
style="height:15%;border:2px solid black;text-align:center;vertical-align:middle;display:table;">
|
style="height:15%;border:2px solid black;text-align:center;vertical-align:middle;display:table;"
|
||||||
|
>
|
||||||
<div style="display: table-cell; vertical-align: middle;">
|
<div style="display: table-cell; vertical-align: middle;">
|
||||||
<strong t-field="o.product_id.default_code"
|
<strong
|
||||||
t-if="o.product_id.default_code"/>
|
t-field="o.product_id.default_code"
|
||||||
|
t-if="o.product_id.default_code"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12 align-middle"
|
<div
|
||||||
style="height:40%;border:2px solid black;text-align:center;vertical-align:middle;display:table;">
|
class="col-12 align-middle"
|
||||||
|
style="height:40%;border:2px solid black;text-align:center;vertical-align:middle;display:table;"
|
||||||
|
>
|
||||||
<div style="display: table-cell; vertical-align: middle;">
|
<div style="display: table-cell; vertical-align: middle;">
|
||||||
<strong t-field="o.product_id.name"/>
|
<strong t-field="o.product_id.name" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-6"
|
<div
|
||||||
style="height:10%;border:2px solid black;text-align:center;vertical-align:middle;display:table;">
|
class="col-6"
|
||||||
<div style="display: table-cell; vertical-align: middle;">
|
style="height:10%;border:2px solid black;text-align:center;vertical-align:middle;"
|
||||||
<span t-esc="float(o.product_qty)"/>
|
>
|
||||||
<span t-field="o.product_id.uom_id.name"/>
|
<div style="vertical-align: middle;">
|
||||||
|
<span t-esc="float(o.product_qty)" />
|
||||||
|
<span t-field="o.product_id.uom_id.name" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-6"
|
<div
|
||||||
style="height:10%;border:2px solid black;text-align:center;vertical-align:middle;display:table;">
|
class="col-6"
|
||||||
<div style="display: table-cell; vertical-align: middle;">
|
style="height:10%;border:2px solid black;text-align:center;vertical-align:middle;"
|
||||||
<span t-esc="float(o.product_uom_qty)"/>
|
>
|
||||||
<span t-field="o.product_uom_id.name"/>
|
<div style="vertical-align: middle;">
|
||||||
|
<span t-esc="float(o.product_uom_qty)" />
|
||||||
|
<span t-field="o.product_uom_id.name" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12"
|
<div
|
||||||
style="height:10%;border:2px solid black;text-align:center;vertical-align:middle;display:table;">
|
class="col-12"
|
||||||
|
style="height:10%;border:2px solid black;text-align:center;vertical-align:middle;display:table;"
|
||||||
|
>
|
||||||
<div style="display: table-cell; vertical-align: middle;">
|
<div style="display: table-cell; vertical-align: middle;">
|
||||||
<span t-field="o.name"/>
|
<span t-field="o.name" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12" style="height:10%;">
|
<div class="col-12" style="height:10%;">
|
||||||
<img t-att-src="'/report/barcode/%s/%s?width=%s&height=%s' % (o.get_barcode_format(), o.name, 320, 20)"
|
<img
|
||||||
style="height:80%; width: 100%;"/>
|
t-att-src="'/report/barcode/%s/%s?width=%s&height=%s' % (o.get_barcode_format(), o.name, 320, 20)"
|
||||||
|
style="height:80%; width: 100%;"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template id="report_kanban_label">
|
<template id="report_kanban_label">
|
||||||
<t t-call="web.basic_layout">
|
<t t-call="web.basic_layout">
|
||||||
<t t-foreach="docs" t-as="o">
|
<t t-foreach="docs" t-as="o">
|
||||||
|
|
||||||
<div class="page">
|
<div class="page">
|
||||||
<t t-call="stock_request_kanban.report_simple_label">
|
<t t-call="stock_request_kanban.report_simple_label">
|
||||||
<t t-set="o" t-value="o"/>
|
<t t-set="o" t-value="o" />
|
||||||
</t>
|
</t>
|
||||||
</div>
|
</div>
|
||||||
</t>
|
</t>
|
||||||
</t>
|
</t>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<report
|
<report
|
||||||
id="action_report_kanban"
|
id="action_report_kanban"
|
||||||
string="Print kanban"
|
string="Print kanban"
|
||||||
model="stock.request.kanban"
|
model="stock.request.kanban"
|
||||||
report_type="qweb-pdf"
|
report_type="qweb-pdf"
|
||||||
name="stock_request_kanban.report_kanban_label"
|
name="stock_request_kanban.report_kanban_label"
|
||||||
file="stock_request_kanban.report_kanban_label"
|
file="stock_request_kanban.report_kanban_label"
|
||||||
paperformat="stock_request_kanban.kanban_paper_format"
|
paperformat="stock_request_kanban.kanban_paper_format"
|
||||||
menu="True"/>
|
menu="True"
|
||||||
|
/>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
odoo.define("stock_request_kanban.StockRequestKanbanController", function(require) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var core = require("web.core");
|
||||||
|
var ListController = require("web.ListController");
|
||||||
|
|
||||||
|
var qweb = core.qweb;
|
||||||
|
|
||||||
|
var StockRequestKanbanController = ListController.extend({
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// Public
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
init: function(parent, model, renderer) {
|
||||||
|
this.context = renderer.state.getContext();
|
||||||
|
return this._super.apply(this, arguments);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
renderButtons: function($node) {
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
var $buttonScan = $(qweb.render("StockRequestKanban.Buttons"));
|
||||||
|
$buttonScan.on("click", this._onOpenWizard.bind(this));
|
||||||
|
|
||||||
|
$buttonScan.prependTo($node.find(".o_list_buttons"));
|
||||||
|
},
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// Handlers
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
_onOpenWizard: function() {
|
||||||
|
var context = {
|
||||||
|
active_model: this.modelName,
|
||||||
|
};
|
||||||
|
this.do_action({
|
||||||
|
res_model: "wizard.stock.request.kanban",
|
||||||
|
views: [[false, "form"]],
|
||||||
|
target: "new",
|
||||||
|
type: "ir.actions.act_window",
|
||||||
|
context: context,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return StockRequestKanbanController;
|
||||||
|
});
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
odoo.define("stock_request_kanban.StockRequestKanbanListView", function(require) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var ListView = require("web.ListView");
|
||||||
|
var StockRequestKanbanController = require("stock_request_kanban.StockRequestKanbanController");
|
||||||
|
var viewRegistry = require("web.view_registry");
|
||||||
|
|
||||||
|
var StockRequestKanbanListView = ListView.extend({
|
||||||
|
config: _.extend({}, ListView.prototype.config, {
|
||||||
|
Controller: StockRequestKanbanController,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
viewRegistry.add("stock_request_kanban_list", StockRequestKanbanListView);
|
||||||
|
|
||||||
|
return StockRequestKanbanListView;
|
||||||
|
});
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<templates id="template" xml:space="preserve">
|
||||||
|
<button t-name="StockRequestKanban.Buttons" class="btn-primary btn" type="button">
|
||||||
|
Scan Kanban
|
||||||
|
</button>
|
||||||
|
</templates>
|
||||||
@@ -1,16 +1,17 @@
|
|||||||
# Copyright 2017 Creu Blanca
|
# Copyright 2017 Creu Blanca
|
||||||
# Copyright 2017 Eficent Business and IT Consulting Services, S.L.
|
# Copyright 2017-2020 ForgeFlow, S.L.
|
||||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
from odoo.tests.common import TransactionCase
|
|
||||||
from reportlab.graphics.barcode import getCodes
|
from reportlab.graphics.barcode import getCodes
|
||||||
|
|
||||||
|
from odoo.tests.common import TransactionCase
|
||||||
|
|
||||||
|
|
||||||
class TestBaseKanban(TransactionCase):
|
class TestBaseKanban(TransactionCase):
|
||||||
|
|
||||||
def pass_code(self, wizard, code):
|
def pass_code(self, wizard, code):
|
||||||
bcc = getCodes()[
|
bcc = getCodes()[self.env["stock.request.kanban"].get_barcode_format()](
|
||||||
self.env['stock.request.kanban'].get_barcode_format()](value=code)
|
value=code
|
||||||
|
)
|
||||||
bcc.validate()
|
bcc.validate()
|
||||||
bcc.encode()
|
bcc.encode()
|
||||||
wizard.on_barcode_scanned(bcc.encoded[1:-1])
|
wizard.on_barcode_scanned(bcc.encoded[1:-1])
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Copyright 2017 Creu Blanca
|
# Copyright 2017 Creu Blanca
|
||||||
# Copyright 2017 Eficent Business and IT Consulting Services, S.L.
|
# Copyright 2017-2020 ForgeFlow, S.L.
|
||||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
from .base_test import TestBaseKanban
|
from .base_test import TestBaseKanban
|
||||||
@@ -8,68 +8,78 @@ from .base_test import TestBaseKanban
|
|||||||
class TestKanban(TestBaseKanban):
|
class TestKanban(TestBaseKanban):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.main_company = self.env.ref('base.main_company')
|
self.main_company = self.env.ref("base.main_company")
|
||||||
self.route = self.env['stock.location.route'].create({
|
self.route = self.env["stock.location.route"].create(
|
||||||
'name': 'Transfer',
|
{
|
||||||
'product_categ_selectable': False,
|
"name": "Transfer",
|
||||||
'product_selectable': True,
|
"product_categ_selectable": False,
|
||||||
'company_id': self.main_company.id,
|
"product_selectable": True,
|
||||||
'sequence': 10,
|
"company_id": self.main_company.id,
|
||||||
})
|
"sequence": 10,
|
||||||
self.product = self.env['product.product'].create({
|
}
|
||||||
'name': 'Product',
|
)
|
||||||
'route_ids': [(4, self.route.id)],
|
self.product = self.env["product.product"].create(
|
||||||
'company_id': False,
|
{"name": "Product", "route_ids": [(4, self.route.id)], "company_id": False}
|
||||||
})
|
)
|
||||||
self.product_2 = self.env['product.product'].create({
|
self.product_2 = self.env["product.product"].create(
|
||||||
'name': 'Product 2',
|
{
|
||||||
'route_ids': [(4, self.route.id)],
|
"name": "Product 2",
|
||||||
'company_id': False,
|
"route_ids": [(4, self.route.id)],
|
||||||
})
|
"company_id": False,
|
||||||
self.kanban_1 = self.env['stock.request.kanban'].create({
|
}
|
||||||
'product_id': self.product.id,
|
)
|
||||||
'product_uom_id': self.product.uom_id.id,
|
self.kanban_1 = self.env["stock.request.kanban"].create(
|
||||||
'product_uom_qty': 1,
|
{
|
||||||
})
|
"product_id": self.product.id,
|
||||||
self.kanban_2 = self.env['stock.request.kanban'].create({
|
"product_uom_id": self.product.uom_id.id,
|
||||||
'product_id': self.product.id,
|
"product_uom_qty": 1,
|
||||||
'product_uom_id': self.product.uom_id.id,
|
}
|
||||||
'product_uom_qty': 1,
|
)
|
||||||
})
|
self.kanban_2 = self.env["stock.request.kanban"].create(
|
||||||
self.kanban_3 = self.env['stock.request.kanban'].create({
|
{
|
||||||
'product_id': self.product_2.id,
|
"product_id": self.product.id,
|
||||||
'product_uom_id': self.product.uom_id.id,
|
"product_uom_id": self.product.uom_id.id,
|
||||||
'product_uom_qty': 1,
|
"product_uom_qty": 1,
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
self.kanban_3 = self.env["stock.request.kanban"].create(
|
||||||
|
{
|
||||||
|
"product_id": self.product_2.id,
|
||||||
|
"product_uom_id": self.product.uom_id.id,
|
||||||
|
"product_uom_qty": 1,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
def test_inventory_warehouse(self):
|
def test_inventory_warehouse(self):
|
||||||
inventory = self.env['stock.inventory.kanban'].create({
|
inventory = self.env["stock.inventory.kanban"].create(
|
||||||
'warehouse_ids': [(4, self.kanban_1.warehouse_id.id)],
|
{"warehouse_ids": [(4, self.kanban_1.warehouse_id.id)]}
|
||||||
})
|
)
|
||||||
inventory.start_inventory()
|
inventory.start_inventory()
|
||||||
self.assertIn(self.kanban_1, inventory.kanban_ids)
|
self.assertIn(self.kanban_1, inventory.kanban_ids)
|
||||||
self.assertIn(self.kanban_1, inventory.missing_kanban_ids)
|
self.assertIn(self.kanban_1, inventory.missing_kanban_ids)
|
||||||
|
|
||||||
def test_inventory_location(self):
|
def test_inventory_location(self):
|
||||||
inventory = self.env['stock.inventory.kanban'].create({
|
inventory = self.env["stock.inventory.kanban"].create(
|
||||||
'location_ids': [(4, self.kanban_1.location_id.id)],
|
{"location_ids": [(4, self.kanban_1.location_id.id)]}
|
||||||
})
|
)
|
||||||
inventory.start_inventory()
|
inventory.start_inventory()
|
||||||
self.assertIn(self.kanban_1, inventory.kanban_ids)
|
self.assertIn(self.kanban_1, inventory.kanban_ids)
|
||||||
self.assertIn(self.kanban_1, inventory.missing_kanban_ids)
|
self.assertIn(self.kanban_1, inventory.missing_kanban_ids)
|
||||||
|
|
||||||
def test_inventory_product(self):
|
def test_inventory_product(self):
|
||||||
inventory = self.env['stock.inventory.kanban'].create({
|
inventory = self.env["stock.inventory.kanban"].create(
|
||||||
'product_ids': [(4, self.product.id)],
|
{"product_ids": [(4, self.product.id)]}
|
||||||
})
|
)
|
||||||
inventory.start_inventory()
|
inventory.start_inventory()
|
||||||
self.assertIn(self.kanban_1, inventory.kanban_ids)
|
self.assertIn(self.kanban_1, inventory.kanban_ids)
|
||||||
self.assertNotIn(self.kanban_3, inventory.kanban_ids)
|
self.assertNotIn(self.kanban_3, inventory.kanban_ids)
|
||||||
self.assertIn(self.kanban_1, inventory.missing_kanban_ids)
|
self.assertIn(self.kanban_1, inventory.missing_kanban_ids)
|
||||||
self.assertEqual(inventory.state, 'in_progress')
|
self.assertEqual(inventory.state, "in_progress")
|
||||||
wizard = self.env['wizard.stock.inventory.kanban'].with_context(
|
wizard = (
|
||||||
default_inventory_kanban_id=inventory.id
|
self.env["wizard.stock.inventory.kanban"]
|
||||||
).create({})
|
.with_context(default_inventory_kanban_id=inventory.id)
|
||||||
|
.create({})
|
||||||
|
)
|
||||||
self.pass_code(wizard, self.kanban_3.name)
|
self.pass_code(wizard, self.kanban_3.name)
|
||||||
self.assertEqual(wizard.status_state, 1)
|
self.assertEqual(wizard.status_state, 1)
|
||||||
self.pass_code(wizard, self.kanban_1.name)
|
self.pass_code(wizard, self.kanban_1.name)
|
||||||
@@ -81,22 +91,22 @@ class TestKanban(TestBaseKanban):
|
|||||||
self.assertNotIn(self.kanban_1, inventory.missing_kanban_ids)
|
self.assertNotIn(self.kanban_1, inventory.missing_kanban_ids)
|
||||||
self.assertIn(self.kanban_1, inventory.scanned_kanban_ids)
|
self.assertIn(self.kanban_1, inventory.scanned_kanban_ids)
|
||||||
inventory.finish_inventory()
|
inventory.finish_inventory()
|
||||||
self.assertEqual(inventory.state, 'finished')
|
self.assertEqual(inventory.state, "finished")
|
||||||
inventory.close_inventory()
|
inventory.close_inventory()
|
||||||
self.assertEqual(inventory.state, 'closed')
|
self.assertEqual(inventory.state, "closed")
|
||||||
|
|
||||||
def test_cancel_inventory(self):
|
def test_cancel_inventory(self):
|
||||||
inventory = self.env['stock.inventory.kanban'].create({
|
inventory = self.env["stock.inventory.kanban"].create(
|
||||||
'product_ids': [(4, self.product.id)],
|
{"product_ids": [(4, self.product.id)]}
|
||||||
})
|
)
|
||||||
inventory.start_inventory()
|
inventory.start_inventory()
|
||||||
self.assertIn(self.kanban_1, inventory.kanban_ids)
|
self.assertIn(self.kanban_1, inventory.kanban_ids)
|
||||||
self.assertNotIn(self.kanban_3, inventory.kanban_ids)
|
self.assertNotIn(self.kanban_3, inventory.kanban_ids)
|
||||||
self.assertIn(self.kanban_1, inventory.missing_kanban_ids)
|
self.assertIn(self.kanban_1, inventory.missing_kanban_ids)
|
||||||
self.assertEqual(inventory.state, 'in_progress')
|
self.assertEqual(inventory.state, "in_progress")
|
||||||
inventory.cancel()
|
inventory.cancel()
|
||||||
self.assertEqual(inventory.state, 'cancelled')
|
self.assertEqual(inventory.state, "cancelled")
|
||||||
inventory.to_draft()
|
inventory.to_draft()
|
||||||
self.assertEqual(inventory.state, 'draft')
|
self.assertEqual(inventory.state, "draft")
|
||||||
self.assertFalse(inventory.kanban_ids)
|
self.assertFalse(inventory.kanban_ids)
|
||||||
self.assertFalse(inventory.scanned_kanban_ids)
|
self.assertFalse(inventory.scanned_kanban_ids)
|
||||||
|
|||||||
@@ -1,71 +1,74 @@
|
|||||||
# Copyright 2017 Creu Blanca
|
# Copyright 2017 Creu Blanca
|
||||||
# Copyright 2017 Eficent Business and IT Consulting Services, S.L.
|
# Copyright 2017-2020 ForgeFlow, S.L.
|
||||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
from .base_test import TestBaseKanban
|
from .base_test import TestBaseKanban
|
||||||
|
|
||||||
|
|
||||||
class TestKanban(TestBaseKanban):
|
class TestKanban(TestBaseKanban):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.main_company = self.env.ref('base.main_company')
|
self.main_company = self.env.ref("base.main_company")
|
||||||
self.warehouse = self.env.ref('stock.warehouse0')
|
self.warehouse = self.env.ref("stock.warehouse0")
|
||||||
self.categ_unit = self.env.ref('uom.product_uom_categ_unit')
|
self.categ_unit = self.env.ref("uom.product_uom_categ_unit")
|
||||||
|
|
||||||
# common data
|
# common data
|
||||||
self.company_2 = self.env['res.company'].create({
|
self.company_2 = self.env["res.company"].create({"name": "Comp2"})
|
||||||
'name': 'Comp2',
|
self.wh2 = self.env["stock.warehouse"].search(
|
||||||
})
|
[("company_id", "=", self.company_2.id)], limit=1
|
||||||
self.wh2 = self.env['stock.warehouse'].search(
|
)
|
||||||
[('company_id', '=', self.company_2.id)], limit=1)
|
self.wh3 = self.env["stock.warehouse"].create(
|
||||||
self.wh3 = self.env['stock.warehouse'].create({
|
{
|
||||||
'name': 'Warehouse TEst',
|
"name": "Warehouse TEst",
|
||||||
'code': 'WH-TEST',
|
"code": "WH-TEST",
|
||||||
'company_id': self.main_company.id,
|
"company_id": self.main_company.id,
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
self.ressuply_loc = self.env['stock.location'].create({
|
self.ressuply_loc = self.env["stock.location"].create(
|
||||||
'name': 'Ressuply',
|
{"name": "Ressuply", "location_id": self.warehouse.view_location_id.id}
|
||||||
'location_id': self.warehouse.view_location_id.id,
|
)
|
||||||
})
|
self.route = self.env["stock.location.route"].create(
|
||||||
self.route = self.env['stock.location.route'].create({
|
{
|
||||||
'name': 'Transfer',
|
"name": "Transfer",
|
||||||
'product_categ_selectable': False,
|
"product_categ_selectable": False,
|
||||||
'product_selectable': True,
|
"product_selectable": True,
|
||||||
'company_id': self.main_company.id,
|
"company_id": self.main_company.id,
|
||||||
'sequence': 10,
|
"sequence": 10,
|
||||||
})
|
}
|
||||||
self.product = self.env['product.product'].create({
|
)
|
||||||
'name': 'Product',
|
self.product = self.env["product.product"].create(
|
||||||
'route_ids': [(4, self.route.id)],
|
{"name": "Product", "route_ids": [(4, self.route.id)], "company_id": False}
|
||||||
'company_id': False,
|
)
|
||||||
})
|
self.uom_dozen = self.env["uom.uom"].create(
|
||||||
self.uom_dozen = self.env['uom.uom'].create({
|
{
|
||||||
'name': 'Test-DozenA',
|
"name": "Test-DozenA",
|
||||||
'category_id': self.categ_unit.id,
|
"category_id": self.categ_unit.id,
|
||||||
'factor_inv': 12,
|
"factor_inv": 12,
|
||||||
'uom_type': 'bigger',
|
"uom_type": "bigger",
|
||||||
'rounding': 0.001})
|
"rounding": 0.001,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
self.env['stock.rule'].create({
|
self.env["stock.rule"].create(
|
||||||
'name': 'Transfer',
|
{
|
||||||
'route_id': self.route.id,
|
"name": "Transfer",
|
||||||
'location_src_id': self.ressuply_loc.id,
|
"route_id": self.route.id,
|
||||||
'location_id': self.warehouse.lot_stock_id.id,
|
"location_src_id": self.ressuply_loc.id,
|
||||||
'action': 'pull_push',
|
"location_id": self.warehouse.lot_stock_id.id,
|
||||||
'picking_type_id': self.warehouse.int_type_id.id,
|
"action": "pull_push",
|
||||||
'procure_method': 'make_to_stock',
|
"picking_type_id": self.warehouse.int_type_id.id,
|
||||||
'warehouse_id': self.warehouse.id,
|
"procure_method": "make_to_stock",
|
||||||
'company_id': self.main_company.id,
|
"warehouse_id": self.warehouse.id,
|
||||||
'propagate': 'False',
|
"company_id": self.main_company.id,
|
||||||
})
|
}
|
||||||
self.env['ir.config_parameter'].set_param(
|
)
|
||||||
'stock_request_kanban.crc', '1')
|
self.env["ir.config_parameter"].set_param("stock_request_kanban.crc", "1")
|
||||||
|
|
||||||
def test_onchanges(self):
|
def test_onchanges(self):
|
||||||
kanban = self.env['stock.request.kanban'].new({})
|
kanban = self.env["stock.request.kanban"].new({})
|
||||||
kanban.product_id = self.product
|
kanban.product_id = self.product
|
||||||
kanban.onchange_product_id()
|
kanban.onchange_product_id()
|
||||||
kanban.company_id = self.main_company
|
kanban.company_id = self.main_company
|
||||||
@@ -80,7 +83,7 @@ class TestKanban(TestBaseKanban):
|
|||||||
self.assertEqual(kanban.warehouse_id, self.warehouse)
|
self.assertEqual(kanban.warehouse_id, self.warehouse)
|
||||||
|
|
||||||
def test_create(self):
|
def test_create(self):
|
||||||
kanban = self.env['stock.request.kanban'].new({})
|
kanban = self.env["stock.request.kanban"].new({})
|
||||||
kanban.product_id = self.product
|
kanban.product_id = self.product
|
||||||
kanban.onchange_product_id()
|
kanban.onchange_product_id()
|
||||||
kanban.product_uom_qty = 1
|
kanban.product_uom_qty = 1
|
||||||
@@ -89,95 +92,109 @@ class TestKanban(TestBaseKanban):
|
|||||||
self.assertEqual(kanban.route_ids, self.route)
|
self.assertEqual(kanban.route_ids, self.route)
|
||||||
|
|
||||||
def test_order_barcodes(self):
|
def test_order_barcodes(self):
|
||||||
kanban_1 = self.env['stock.request.kanban'].create({
|
kanban_1 = self.env["stock.request.kanban"].create(
|
||||||
'product_id': self.product.id,
|
{
|
||||||
'product_uom_id': self.product.uom_id.id,
|
"product_id": self.product.id,
|
||||||
'product_uom_qty': 1,
|
"product_uom_id": self.product.uom_id.id,
|
||||||
})
|
"product_uom_qty": 1,
|
||||||
kanban_2 = self.env['stock.request.kanban'].create({
|
}
|
||||||
'product_id': self.product.id,
|
)
|
||||||
'product_uom_id': self.product.uom_id.id,
|
kanban_2 = self.env["stock.request.kanban"].create(
|
||||||
'product_uom_qty': 1,
|
{
|
||||||
})
|
"product_id": self.product.id,
|
||||||
kanban_3 = self.env['stock.request.kanban'].create({
|
"product_uom_id": self.product.uom_id.id,
|
||||||
'product_id': self.product.id,
|
"product_uom_qty": 1,
|
||||||
'product_uom_id': self.product.uom_id.id,
|
}
|
||||||
'product_uom_qty': 1,
|
)
|
||||||
'company_id': self.main_company.id,
|
kanban_3 = self.env["stock.request.kanban"].create(
|
||||||
'warehouse_id': self.wh3.id,
|
{
|
||||||
'location_id': self.wh3.lot_stock_id.id,
|
"product_id": self.product.id,
|
||||||
})
|
"product_uom_id": self.product.uom_id.id,
|
||||||
order = self.env['stock.request.order'].create({
|
"product_uom_qty": 1,
|
||||||
'company_id': self.main_company.id,
|
"company_id": self.main_company.id,
|
||||||
'warehouse_id': self.warehouse.id,
|
"warehouse_id": self.wh3.id,
|
||||||
'location_id': self.warehouse.lot_stock_id.id,
|
"location_id": self.wh3.lot_stock_id.id,
|
||||||
})
|
}
|
||||||
wizard = self.env['wizard.stock.request.order.kanban'].with_context(
|
)
|
||||||
default_order_id=order.id
|
order = self.env["stock.request.order"].create(
|
||||||
).create({})
|
{
|
||||||
|
"company_id": self.main_company.id,
|
||||||
|
"warehouse_id": self.warehouse.id,
|
||||||
|
"location_id": self.warehouse.lot_stock_id.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
wizard = (
|
||||||
|
self.env["wizard.stock.request.order.kanban"]
|
||||||
|
.with_context(default_order_id=order.id)
|
||||||
|
.create({})
|
||||||
|
)
|
||||||
with self.assertRaises(ValidationError):
|
with self.assertRaises(ValidationError):
|
||||||
wizard.on_barcode_scanned(kanban_1.name)
|
wizard.on_barcode_scanned(kanban_1.name)
|
||||||
self.pass_code(wizard, kanban_1.name)
|
self.pass_code(wizard, kanban_1.name)
|
||||||
self.assertEqual(wizard.status_state, 0)
|
self.assertEqual(wizard.status_state, 0)
|
||||||
self.assertTrue(order.stock_request_ids.filtered(
|
self.assertTrue(
|
||||||
lambda r: r.kanban_id == kanban_1
|
order.stock_request_ids.filtered(lambda r: r.kanban_id == kanban_1)
|
||||||
))
|
)
|
||||||
self.pass_code(wizard, kanban_2.name)
|
self.pass_code(wizard, kanban_2.name)
|
||||||
self.assertTrue(order.stock_request_ids.filtered(
|
self.assertTrue(
|
||||||
lambda r: r.kanban_id == kanban_2
|
order.stock_request_ids.filtered(lambda r: r.kanban_id == kanban_2)
|
||||||
))
|
)
|
||||||
self.assertEqual(wizard.status_state, 0)
|
self.assertEqual(wizard.status_state, 0)
|
||||||
self.pass_code(wizard, kanban_1.name)
|
self.pass_code(wizard, kanban_1.name)
|
||||||
self.assertEqual(wizard.status_state, 1)
|
self.assertEqual(wizard.status_state, 1)
|
||||||
self.pass_code(wizard, kanban_2.name+kanban_1.name)
|
self.pass_code(wizard, kanban_2.name + kanban_1.name)
|
||||||
self.assertEqual(wizard.status_state, 1)
|
self.assertEqual(wizard.status_state, 1)
|
||||||
with self.assertRaises(ValidationError):
|
with self.assertRaises(ValidationError):
|
||||||
self.pass_code(wizard, kanban_3.name)
|
self.pass_code(wizard, kanban_3.name)
|
||||||
|
|
||||||
def test_barcodes(self):
|
def test_barcodes(self):
|
||||||
kanban_1 = self.env['stock.request.kanban'].create({
|
kanban_1 = self.env["stock.request.kanban"].create(
|
||||||
'product_id': self.product.id,
|
{
|
||||||
'product_uom_id': self.product.uom_id.id,
|
"product_id": self.product.id,
|
||||||
'product_uom_qty': 1,
|
"product_uom_id": self.product.uom_id.id,
|
||||||
})
|
"product_uom_qty": 1,
|
||||||
kanban_2 = self.env['stock.request.kanban'].create({
|
}
|
||||||
'product_id': self.product.id,
|
)
|
||||||
'product_uom_id': self.product.uom_id.id,
|
kanban_2 = self.env["stock.request.kanban"].create(
|
||||||
'product_uom_qty': 1,
|
{
|
||||||
})
|
"product_id": self.product.id,
|
||||||
kanban_3 = self.env['stock.request.kanban'].create({
|
"product_uom_id": self.product.uom_id.id,
|
||||||
'product_id': self.product.id,
|
"product_uom_qty": 1,
|
||||||
'product_uom_id': self.product.uom_id.id,
|
}
|
||||||
'product_uom_qty': 1,
|
)
|
||||||
})
|
kanban_3 = self.env["stock.request.kanban"].create(
|
||||||
wizard = self.env['wizard.stock.request.kanban'].with_context(
|
{
|
||||||
).create({})
|
"product_id": self.product.id,
|
||||||
|
"product_uom_id": self.product.uom_id.id,
|
||||||
|
"product_uom_qty": 1,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
wizard = self.env["wizard.stock.request.kanban"].with_context().create({})
|
||||||
with self.assertRaises(ValidationError):
|
with self.assertRaises(ValidationError):
|
||||||
wizard.on_barcode_scanned(kanban_1.name)
|
wizard.on_barcode_scanned(kanban_1.name)
|
||||||
self.assertFalse(self.env['stock.request'].search(
|
self.assertFalse(
|
||||||
[('kanban_id', '=', kanban_1.id)])
|
self.env["stock.request"].search([("kanban_id", "=", kanban_1.id)])
|
||||||
)
|
)
|
||||||
self.pass_code(wizard, kanban_1.name)
|
self.pass_code(wizard, kanban_1.name)
|
||||||
self.assertEqual(wizard.status_state, 0)
|
self.assertEqual(wizard.status_state, 0)
|
||||||
self.assertTrue(self.env['stock.request'].search(
|
self.assertTrue(
|
||||||
[('kanban_id', '=', kanban_1.id)])
|
self.env["stock.request"].search([("kanban_id", "=", kanban_1.id)])
|
||||||
)
|
)
|
||||||
self.assertFalse(self.env['stock.request'].search(
|
self.assertFalse(
|
||||||
[('kanban_id', '=', kanban_2.id)])
|
self.env["stock.request"].search([("kanban_id", "=", kanban_2.id)])
|
||||||
)
|
)
|
||||||
self.pass_code(wizard, kanban_2.name)
|
self.pass_code(wizard, kanban_2.name)
|
||||||
self.assertTrue(self.env['stock.request'].search(
|
self.assertTrue(
|
||||||
[('kanban_id', '=', kanban_2.id)])
|
self.env["stock.request"].search([("kanban_id", "=", kanban_2.id)])
|
||||||
)
|
)
|
||||||
with self.assertRaises(ValidationError):
|
with self.assertRaises(ValidationError):
|
||||||
wizard.on_barcode_scanned(kanban_3.name)
|
wizard.on_barcode_scanned(kanban_3.name)
|
||||||
self.assertFalse(self.env['stock.request'].search(
|
self.assertFalse(
|
||||||
[('kanban_id', '=', kanban_3.id)])
|
self.env["stock.request"].search([("kanban_id", "=", kanban_3.id)])
|
||||||
)
|
)
|
||||||
self.env['ir.config_parameter'].set_param(
|
self.env["ir.config_parameter"].set_param("stock_request_kanban.crc", "0")
|
||||||
'stock_request_kanban.crc', '0')
|
|
||||||
wizard.on_barcode_scanned(kanban_3.name)
|
wizard.on_barcode_scanned(kanban_3.name)
|
||||||
self.assertEqual(wizard.status_state, 0)
|
self.assertEqual(wizard.status_state, 0)
|
||||||
self.assertTrue(self.env['stock.request'].search(
|
self.assertTrue(
|
||||||
[('kanban_id', '=', kanban_3.id)])
|
self.env["stock.request"].search([("kanban_id", "=", kanban_3.id)])
|
||||||
)
|
)
|
||||||
|
|||||||
57
stock_request_kanban/views/product_views.xml
Normal file
57
stock_request_kanban/views/product_views.xml
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<!-- Copyright 2020 ForgeFlow, S.L.
|
||||||
|
License LGPL-3.0 or later (https://www.gnu.org/licenses/gpl). -->
|
||||||
|
<odoo>
|
||||||
|
<record id="product_product_form_view_kanban_card_button" model="ir.ui.view">
|
||||||
|
<field name="name">product.product.stock.request.kanban</field>
|
||||||
|
<field name="model">product.product</field>
|
||||||
|
<field name="inherit_id" ref="product.product_normal_form_view" />
|
||||||
|
<field
|
||||||
|
name="groups_id"
|
||||||
|
eval="[(4, ref('stock_request.group_stock_request_user'))]"
|
||||||
|
/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<div name="button_box" position="inside">
|
||||||
|
<button
|
||||||
|
class="oe_stat_button"
|
||||||
|
name="action_view_kanban_cards"
|
||||||
|
type="object"
|
||||||
|
attrs="{'invisible':[('type', 'not in', ['product', 'consu'])]}"
|
||||||
|
icon="fa-barcode"
|
||||||
|
>
|
||||||
|
<field
|
||||||
|
string="Kanban Cards"
|
||||||
|
name="kanban_card_count"
|
||||||
|
widget="statinfo"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
<record id="product_template_form_view_bom_button" model="ir.ui.view">
|
||||||
|
<field name="name">product.template.stock.request.kanban</field>
|
||||||
|
<field name="model">product.template</field>
|
||||||
|
<field name="inherit_id" ref="product.product_template_only_form_view" />
|
||||||
|
<field
|
||||||
|
name="groups_id"
|
||||||
|
eval="[(4, ref('stock_request.group_stock_request_user'))]"
|
||||||
|
/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<div name="button_box" position="inside">
|
||||||
|
<button
|
||||||
|
class="oe_stat_button"
|
||||||
|
name="action_view_kanban_cards"
|
||||||
|
type="object"
|
||||||
|
attrs="{'invisible':[('type', 'not in', ['product', 'consu'])]}"
|
||||||
|
icon="fa-barcode"
|
||||||
|
>
|
||||||
|
<field
|
||||||
|
string="Kanban Cards"
|
||||||
|
name="kanban_card_count"
|
||||||
|
widget="statinfo"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
@@ -1,97 +1,122 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record id="view_stock_inventory_kanban_tree" model="ir.ui.view">
|
<record id="view_stock_inventory_kanban_tree" model="ir.ui.view">
|
||||||
<field name="name">stock.inventory.kanban.tree</field>
|
<field name="name">stock.inventory.kanban.tree</field>
|
||||||
<field name="model">stock.inventory.kanban</field>
|
<field name="model">stock.inventory.kanban</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree string="Stock Inventories">
|
<tree string="Stock Inventories">
|
||||||
<field name="name"/>
|
<field name="name" />
|
||||||
<field name="count_missing_kanbans"/>
|
<field name="count_missing_kanbans" />
|
||||||
<field name="state"/>
|
<field name="state" />
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="view_stock_inventory_kanban_form" model="ir.ui.view">
|
<record id="view_stock_inventory_kanban_form" model="ir.ui.view">
|
||||||
<field name="name">stock.inventory.kanban.form</field>
|
<field name="name">stock.inventory.kanban.form</field>
|
||||||
<field name="model">stock.inventory.kanban</field>
|
<field name="model">stock.inventory.kanban</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Stock Inventories">
|
<form string="Stock Inventories">
|
||||||
<header>
|
<header>
|
||||||
<button name="start_inventory" type="object" string="Start"
|
<button
|
||||||
states="draft" class="btn-primary"
|
name="start_inventory"
|
||||||
/>
|
type="object"
|
||||||
<button name="finish_inventory" type="object" string="Finish"
|
string="Start"
|
||||||
states="in_progress" class="btn-primary"
|
states="draft"
|
||||||
/>
|
class="btn-primary"
|
||||||
<button name="print_missing_kanbans" type="object" string="Print missing"
|
/>
|
||||||
states="finished"
|
<button
|
||||||
/>
|
name="finish_inventory"
|
||||||
<button name="close_inventory" type="object" string="Close"
|
type="object"
|
||||||
states="finished" class="btn-primary"
|
string="Finish"
|
||||||
/>
|
states="in_progress"
|
||||||
<button name="cancel" type="object" string="Cancel"
|
class="btn-primary"
|
||||||
states="draft,in_progress,finished"
|
/>
|
||||||
/>
|
<button
|
||||||
<button name="to_draft" type="object" string="Set to draft"
|
name="print_missing_kanbans"
|
||||||
states="cancelled"
|
type="object"
|
||||||
/>
|
string="Print missing"
|
||||||
<field name="state" widget="statusbar"/>
|
states="finished"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
name="close_inventory"
|
||||||
|
type="object"
|
||||||
|
string="Close"
|
||||||
|
states="finished"
|
||||||
|
class="btn-primary"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
name="cancel"
|
||||||
|
type="object"
|
||||||
|
string="Cancel"
|
||||||
|
states="draft,in_progress,finished"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
name="to_draft"
|
||||||
|
type="object"
|
||||||
|
string="Set to draft"
|
||||||
|
states="cancelled"
|
||||||
|
/>
|
||||||
|
<field name="state" widget="statusbar" />
|
||||||
</header>
|
</header>
|
||||||
<sheet>
|
<sheet>
|
||||||
<div class="oe_button_box" name="button_box">
|
<div class="oe_button_box" name="button_box">
|
||||||
<button name="%(stock_request_kanban.wizard_stock_inventory_kanban_action)d"
|
<button
|
||||||
type="action"
|
name="%(stock_request_kanban.wizard_stock_inventory_kanban_action)d"
|
||||||
icon="fa-barcode"
|
type="action"
|
||||||
string="Scan"
|
icon="fa-barcode"
|
||||||
states="in_progress"
|
string="Scan"
|
||||||
class="oe_read_only"
|
states="in_progress"
|
||||||
|
class="oe_read_only"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="oe_title">
|
<div class="oe_title">
|
||||||
<label for="name" string="Inventory Kanban" />
|
<label for="name" string="Inventory Kanban" />
|
||||||
<h1>
|
<h1>
|
||||||
<field name="name" readonly="1"/>
|
<field name="name" readonly="1" />
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<group>
|
<group>
|
||||||
<field name="warehouse_ids" widget="many2many_tags" groups="stock.group_stock_multi_locations"/>
|
<field
|
||||||
<field name="location_ids" widget="many2many_tags" groups="stock.group_stock_multi_locations"/>
|
name="warehouse_ids"
|
||||||
<field name="product_ids" widget="many2many_tags"/>
|
widget="many2many_tags"
|
||||||
|
groups="stock.group_stock_multi_locations"
|
||||||
|
/>
|
||||||
|
<field
|
||||||
|
name="location_ids"
|
||||||
|
widget="many2many_tags"
|
||||||
|
groups="stock.group_stock_multi_locations"
|
||||||
|
/>
|
||||||
|
<field name="product_ids" widget="many2many_tags" />
|
||||||
</group>
|
</group>
|
||||||
<notebook>
|
<notebook>
|
||||||
<page string="Kanban" id="kanban">
|
<page string="Kanban" id="kanban">
|
||||||
<field name="kanban_ids"/>
|
<field name="kanban_ids" />
|
||||||
</page>
|
</page>
|
||||||
<page string="Missing" id="missing">
|
<page string="Missing" id="missing">
|
||||||
<field name="missing_kanban_ids"/>
|
<field name="missing_kanban_ids" />
|
||||||
</page>
|
</page>
|
||||||
<page string="Scanned" id="scanned">
|
<page string="Scanned" id="scanned">
|
||||||
<field name="scanned_kanban_ids"/>
|
<field name="scanned_kanban_ids" />
|
||||||
</page>
|
</page>
|
||||||
</notebook>
|
</notebook>
|
||||||
</sheet>
|
</sheet>
|
||||||
<div class="oe_chatter">
|
<div class="oe_chatter">
|
||||||
<field name="message_follower_ids" widget="mail_followers"/>
|
<field name="message_follower_ids" widget="mail_followers" />
|
||||||
<field name="activity_ids" widget="mail_activity"/>
|
<field name="activity_ids" widget="mail_activity" />
|
||||||
<field name="message_ids" widget="mail_thread"/>
|
<field name="message_ids" widget="mail_thread" />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="stock_inventory_kanban_action" model="ir.actions.act_window">
|
<record id="stock_inventory_kanban_action" model="ir.actions.act_window">
|
||||||
<field name="name">Stock Inventory Kanbans</field>
|
<field name="name">Stock Inventory Kanbans</field>
|
||||||
<field name="res_model">stock.inventory.kanban</field>
|
<field name="res_model">stock.inventory.kanban</field>
|
||||||
<field name="type">ir.actions.act_window</field>
|
<field name="type">ir.actions.act_window</field>
|
||||||
<field name="view_type">form</field>
|
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
<field name="help" type="html">
|
<field name="help" type="html">
|
||||||
<p class="oe_view_nocontent_create">
|
<p class="oe_view_nocontent_create">
|
||||||
Click to add a Stock Inventory Kanban.
|
Click to add a Stock Inventory Kanban.
|
||||||
</p>
|
</p>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -1,145 +1,198 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<!-- Copyright 2017 Eficent
|
<!-- Copyright 2017-2020 ForgeFlow, S.L.
|
||||||
License LGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
|
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). -->
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record id="view_stock_request_kanban_tree" model="ir.ui.view">
|
<record id="view_stock_request_kanban_tree" model="ir.ui.view">
|
||||||
<field name="name">stock.request.kanban.tree</field>
|
<field name="name">stock.request.kanban.tree</field>
|
||||||
<field name="model">stock.request.kanban</field>
|
<field name="model">stock.request.kanban</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree string="Stock Requests" decoration-muted="active == 'false'" decoration-bf="message_needaction==True">
|
<tree
|
||||||
<field name="message_needaction" invisible="1"/>
|
string="Stock Requests"
|
||||||
<field name="name"/>
|
decoration-muted="active == 'false'"
|
||||||
<field name="warehouse_id" groups="stock.group_stock_multi_locations"/>
|
decoration-bf="message_needaction==True"
|
||||||
<field name="location_id" groups="stock.group_stock_multi_locations"/>
|
>
|
||||||
<field name="route_id" options="{'no_create': True}" groups="stock.group_stock_multi_locations"/>
|
<field name="message_needaction" invisible="1" />
|
||||||
<field name="product_id"/>
|
<field name="name" />
|
||||||
<field name="product_uom_id"
|
<field name="warehouse_id" groups="stock.group_stock_multi_locations" />
|
||||||
options="{'no_open': True, 'no_create': True}" groups="uom.group_uom"/>
|
<field name="location_id" groups="stock.group_stock_multi_locations" />
|
||||||
<field name="product_uom_qty"/>
|
<field
|
||||||
<field name="active" invisible="1"/>
|
name="route_id"
|
||||||
|
options="{'no_create': True}"
|
||||||
|
groups="stock.group_stock_multi_locations"
|
||||||
|
/>
|
||||||
|
<field name="product_id" />
|
||||||
|
<field
|
||||||
|
name="product_uom_id"
|
||||||
|
options="{'no_open': True, 'no_create': True}"
|
||||||
|
groups="uom.group_uom"
|
||||||
|
/>
|
||||||
|
<field name="product_uom_qty" />
|
||||||
|
<field name="active" invisible="1" />
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="stock_request_kanban_search">
|
<record model="ir.ui.view" id="stock_request_kanban_search">
|
||||||
<field name="name">stock.request.kanban.search</field>
|
<field name="name">stock.request.kanban.search</field>
|
||||||
<field name="model">stock.request.kanban</field>
|
<field name="model">stock.request.kanban</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<search string="Stock Requests Kanban">
|
<search string="Stock Requests Kanban">
|
||||||
<field name="name" string="Stock Requests Kanban"/>
|
<field name="name" string="Stock Requests Kanban" />
|
||||||
<field name="warehouse_id" groups="stock.group_stock_multi_locations"/>
|
<field name="warehouse_id" groups="stock.group_stock_multi_locations" />
|
||||||
<field name="location_id" groups="stock.group_stock_multi_locations"/>
|
<field name="location_id" groups="stock.group_stock_multi_locations" />
|
||||||
<field name="company_id" groups="base.group_multi_company"/>
|
<field name="company_id" groups="base.group_multi_company" />
|
||||||
<field name="product_id"/>
|
<field name="product_id" />
|
||||||
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
|
<filter
|
||||||
|
string="Archived"
|
||||||
|
name="inactive"
|
||||||
|
domain="[('active','=',False)]"
|
||||||
|
/>
|
||||||
<group expand="0" string="Group By">
|
<group expand="0" string="Group By">
|
||||||
<filter name="warehouse" string="Warehouse" domain="[]" context="{'group_by':'warehouse_id'}"/>
|
<filter
|
||||||
<filter name="location" string="Location" domain="[]" context="{'group_by':'location_id'}"/>
|
name="warehouse"
|
||||||
|
string="Warehouse"
|
||||||
|
domain="[]"
|
||||||
|
context="{'group_by':'warehouse_id'}"
|
||||||
|
/>
|
||||||
|
<filter
|
||||||
|
name="location"
|
||||||
|
string="Location"
|
||||||
|
domain="[]"
|
||||||
|
context="{'group_by':'location_id'}"
|
||||||
|
/>
|
||||||
</group>
|
</group>
|
||||||
</search>
|
</search>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="view_stock_request_kanban_form" model="ir.ui.view">
|
<record id="view_stock_request_kanban_form" model="ir.ui.view">
|
||||||
<field name="name">stock.request.kanban.form</field>
|
<field name="name">stock.request.kanban.form</field>
|
||||||
<field name="model">stock.request.kanban</field>
|
<field name="model">stock.request.kanban</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Stock Requests">
|
<form string="Stock Requests">
|
||||||
<header/>
|
<header />
|
||||||
<sheet>
|
<sheet>
|
||||||
<div class="oe_button_box" name="button_box"/>
|
<div class="oe_button_box" name="button_box" />
|
||||||
<div class="oe_title">
|
<div class="oe_title">
|
||||||
<label for="name" string="Stock Request Kanban" />
|
<label for="name" string="Stock Request Kanban" />
|
||||||
<h1>
|
<h1>
|
||||||
<field name="name" readonly="1"/>
|
<field name="name" readonly="1" />
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<group>
|
<group>
|
||||||
<group>
|
<group>
|
||||||
<field name="product_id"/>
|
<field name="product_id" />
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="warehouse_id" widget="selection" groups="stock.group_stock_multi_locations"/>
|
<field
|
||||||
<field name="location_id" groups="stock.group_stock_multi_locations"/>
|
name="warehouse_id"
|
||||||
<field name="route_id"
|
widget="selection"
|
||||||
options="{'no_create': True}" groups="stock.group_stock_multi_locations"/>
|
groups="stock.group_stock_multi_locations"
|
||||||
<field name="route_ids" invisible="1"/>
|
/>
|
||||||
<field name="procurement_group_id"
|
<field
|
||||||
groups="stock.group_adv_location"/>
|
name="location_id"
|
||||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
groups="stock.group_stock_multi_locations"
|
||||||
|
/>
|
||||||
|
<field
|
||||||
|
name="route_id"
|
||||||
|
options="{'no_create': True}"
|
||||||
|
groups="stock.group_stock_multi_locations"
|
||||||
|
/>
|
||||||
|
<field name="route_ids" invisible="1" />
|
||||||
|
<field
|
||||||
|
name="procurement_group_id"
|
||||||
|
groups="stock.group_adv_location"
|
||||||
|
/>
|
||||||
|
<field
|
||||||
|
name="company_id"
|
||||||
|
groups="base.group_multi_company"
|
||||||
|
options="{'no_create': True}"
|
||||||
|
/>
|
||||||
</group>
|
</group>
|
||||||
<group name="quantities">
|
<group name="quantities">
|
||||||
<label for="product_uom_qty"/>
|
<label for="product_uom_qty" />
|
||||||
<div>
|
<div>
|
||||||
<field name="product_uom_qty"
|
<field name="product_uom_qty" class="oe_inline" />
|
||||||
class="oe_inline"/>
|
<field
|
||||||
<field name="product_uom_id"
|
name="product_uom_id"
|
||||||
class="oe_inline"
|
class="oe_inline"
|
||||||
options="{'no_open': True, 'no_create': True}"
|
options="{'no_open': True, 'no_create': True}"
|
||||||
groups="uom.group_uom"/>
|
groups="uom.group_uom"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
</sheet>
|
</sheet>
|
||||||
<div class="oe_chatter">
|
<div class="oe_chatter">
|
||||||
<field name="message_follower_ids" widget="mail_followers"/>
|
<field name="message_follower_ids" widget="mail_followers" />
|
||||||
<field name="activity_ids" widget="mail_activity"/>
|
<field name="activity_ids" widget="mail_activity" />
|
||||||
<field name="message_ids" widget="mail_thread"/>
|
<field name="message_ids" widget="mail_thread" />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- Partner Kanban View -->
|
<!-- Partner Kanban View -->
|
||||||
<record model="ir.ui.view" id="stock_request_kanban_kanban_view">
|
<record model="ir.ui.view" id="stock_request_kanban_kanban_view">
|
||||||
<field name="name">stock.request.kanban.kanban</field>
|
<field name="name">stock.request.kanban.kanban</field>
|
||||||
<field name="model">stock.request.kanban</field>
|
<field name="model">stock.request.kanban</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<kanban class="o_res_partner_kanban">
|
<kanban class="o_res_partner_kanban">
|
||||||
<field name="id"/>
|
<field name="id" />
|
||||||
<field name="name"/>
|
<field name="name" />
|
||||||
<field name="product_id"/>
|
<field name="product_id" />
|
||||||
<field name="display_name"/>
|
<field name="display_name" />
|
||||||
<field name="warehouse_id"/>
|
<field name="warehouse_id" />
|
||||||
<field name="location_id"/>
|
<field name="location_id" />
|
||||||
<field name="product_qty"/>
|
<field name="product_qty" />
|
||||||
<templates>
|
<templates>
|
||||||
<t t-name="kanban-box">
|
<t t-name="kanban-box">
|
||||||
<div class="oe_kanban_global_click o_res_partner_kanban">
|
<div class="oe_kanban_global_click o_res_partner_kanban">
|
||||||
|
<div class="o_kanban_image">
|
||||||
<div class="o_kanban_image">
|
<img
|
||||||
<img t-att-src="kanban_image('product.product', 'image_small', record.product_id.raw_value)" alt="Kanban Image"/>
|
t-att-src="kanban_image('product.product', 'image_small', record.product_id.raw_value)"
|
||||||
</div>
|
alt="Kanban Image"
|
||||||
<div class="oe_kanban_details">
|
/>
|
||||||
<strong class="o_kanban_record_title"><field name="display_name"/></strong>
|
|
||||||
<div class="o_kanban_tags_section"/>
|
|
||||||
<ul>
|
|
||||||
<li t-if="record.product_id.raw_value"><field name="product_id"/></li>
|
|
||||||
<li t-if="record.warehouse_id.raw_value" groups="stock.group_stock_multi_locations"><field name="warehouse_id"/></li>
|
|
||||||
<li t-if="record.location_id.raw_value" groups="stock.group_stock_multi_locations"><field name="location_id"/></li>
|
|
||||||
<li t-if="record.product_qty"><field name="product_qty"/> <field name="product_uom_id"/></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="oe_kanban_details">
|
||||||
</t>
|
<strong class="o_kanban_record_title">
|
||||||
</templates>
|
<field name="display_name" />
|
||||||
</kanban>
|
</strong>
|
||||||
</field>
|
<div class="o_kanban_tags_section" />
|
||||||
</record>
|
<ul>
|
||||||
|
<li t-if="record.product_id.raw_value">
|
||||||
|
<field name="product_id" />
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
t-if="record.warehouse_id.raw_value"
|
||||||
|
groups="stock.group_stock_multi_locations"
|
||||||
|
>
|
||||||
|
<field name="warehouse_id" />
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
t-if="record.location_id.raw_value"
|
||||||
|
groups="stock.group_stock_multi_locations"
|
||||||
|
>
|
||||||
|
<field name="location_id" />
|
||||||
|
</li>
|
||||||
|
<li t-if="record.product_qty">
|
||||||
|
<field name="product_qty" />
|
||||||
|
<field name="product_uom_id" />
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
</templates>
|
||||||
|
</kanban>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
<record id="stock_request_kanban_action" model="ir.actions.act_window">
|
<record id="stock_request_kanban_action" model="ir.actions.act_window">
|
||||||
<field name="name">Stock Request Kanbans</field>
|
<field name="name">Stock Request Kanbans</field>
|
||||||
<field name="res_model">stock.request.kanban</field>
|
<field name="res_model">stock.request.kanban</field>
|
||||||
<field name="type">ir.actions.act_window</field>
|
<field name="type">ir.actions.act_window</field>
|
||||||
<field name="view_type">form</field>
|
|
||||||
<field name="view_mode">kanban,tree,form</field>
|
<field name="view_mode">kanban,tree,form</field>
|
||||||
<field name="help" type="html">
|
<field name="help" type="html">
|
||||||
<p class="oe_view_nocontent_create">
|
<p class="oe_view_nocontent_create">
|
||||||
Click to add a Stock Request Kanban.
|
Click to add a Stock Request Kanban.
|
||||||
</p>
|
</p>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -1,22 +1,25 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
|
<menuitem
|
||||||
<menuitem id="stock_request_kanban_menu"
|
id="stock_request_kanban_menu"
|
||||||
name="Kanban cards"
|
name="Kanban cards"
|
||||||
parent="stock_request.menu_stock_request_master_data"
|
parent="stock_request.menu_stock_request_master_data"
|
||||||
action="stock_request_kanban_action"
|
action="stock_request_kanban_action"
|
||||||
groups="stock_request.group_stock_request_manager"
|
groups="stock_request.group_stock_request_manager"
|
||||||
sequence="110"/>
|
sequence="110"
|
||||||
|
/>
|
||||||
<menuitem id="menu_wizard_stock_request_kanban"
|
<menuitem
|
||||||
name="Request from Kanban cards"
|
id="menu_wizard_stock_request_kanban"
|
||||||
parent="stock_request.menu_stock_request_operations"
|
name="Request from Kanban cards"
|
||||||
action="wizard_stock_request_kanban_action"
|
parent="stock_request.menu_stock_request_operations"
|
||||||
sequence="40"/>
|
action="wizard_stock_request_kanban_action"
|
||||||
|
sequence="40"
|
||||||
<menuitem id="menu_wizard_stock_inventory_kanban"
|
/>
|
||||||
name="Inventory"
|
<menuitem
|
||||||
parent="stock_request.menu_stock_request_operations"
|
id="menu_wizard_stock_inventory_kanban"
|
||||||
action="stock_inventory_kanban_action"
|
name="Inventory"
|
||||||
sequence="60"/>
|
parent="stock_request.menu_stock_request_operations"
|
||||||
|
action="stock_inventory_kanban_action"
|
||||||
|
sequence="60"
|
||||||
|
/>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -1,21 +1,20 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="stock_request_order_form">
|
<record model="ir.ui.view" id="stock_request_order_form">
|
||||||
<field name="name">stock.request.order.form</field>
|
<field name="name">stock.request.order.form</field>
|
||||||
<field name="model">stock.request.order</field>
|
<field name="model">stock.request.order</field>
|
||||||
<field name="inherit_id" ref="stock_request.stock_request_order_form"/>
|
<field name="inherit_id" ref="stock_request.stock_request_order_form" />
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<xpath expr="//div[@name='button_box']" position="inside">
|
<xpath expr="//div[@name='button_box']" position="inside">
|
||||||
<button name="%(stock_request_kanban.wizard_stock_request_order_kanban_action)d"
|
<button
|
||||||
type="action"
|
name="%(stock_request_kanban.wizard_stock_request_order_kanban_action)d"
|
||||||
icon="fa-barcode"
|
type="action"
|
||||||
string="Scan"
|
icon="fa-barcode"
|
||||||
states="draft"
|
string="Scan"
|
||||||
class="oe_read_only"
|
states="draft"
|
||||||
|
class="oe_read_only"
|
||||||
/>
|
/>
|
||||||
</xpath>
|
</xpath>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
31
stock_request_kanban/views/stock_request_views.xml
Normal file
31
stock_request_kanban/views/stock_request_views.xml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<!-- Copyright 2017 Eficent
|
||||||
|
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). -->
|
||||||
|
<odoo>
|
||||||
|
<template
|
||||||
|
id="stock_request_kanban_assets_backend"
|
||||||
|
name="stock_request_kanban assets"
|
||||||
|
inherit_id="web.assets_backend"
|
||||||
|
>
|
||||||
|
<xpath expr="." position="inside">
|
||||||
|
<script
|
||||||
|
type="text/javascript"
|
||||||
|
src="/stock_request_kanban/static/src/js/stock_request_kanban_scan_controller.js"
|
||||||
|
/>
|
||||||
|
<script
|
||||||
|
type="text/javascript"
|
||||||
|
src="/stock_request_kanban/static/src/js/stock_request_kanban_scan_view.js"
|
||||||
|
/>
|
||||||
|
</xpath>
|
||||||
|
</template>
|
||||||
|
<record id="view_stock_request_tree" model="ir.ui.view">
|
||||||
|
<field name="name">stock.request.tree</field>
|
||||||
|
<field name="model">stock.request</field>
|
||||||
|
<field name="inherit_id" ref="stock_request.view_stock_request_tree" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<tree position="attributes">
|
||||||
|
<attribute name="js_class">stock_request_kanban_list</attribute>
|
||||||
|
</tree>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
@@ -1,24 +1,20 @@
|
|||||||
# Copyright 2017 Creu Blanca
|
# Copyright 2017 Creu Blanca
|
||||||
# Copyright 2017 Eficent Business and IT Consulting Services, S.L.
|
# Copyright 2017-2020 ForgeFlow, S.L.
|
||||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
from odoo import fields, models, _
|
from odoo import _, fields, models
|
||||||
|
|
||||||
|
|
||||||
class WizardStockRequestOrderKanbanAbstract(models.TransientModel):
|
class WizardStockInventoryKanban(models.TransientModel):
|
||||||
_name = "wizard.stock.inventory.kanban"
|
_name = "wizard.stock.inventory.kanban"
|
||||||
|
_description = "Stock Inventory Kanban Wizard"
|
||||||
_inherit = "wizard.stock.request.kanban.abstract"
|
_inherit = "wizard.stock.request.kanban.abstract"
|
||||||
|
|
||||||
inventory_kanban_id = fields.Many2one(
|
inventory_kanban_id = fields.Many2one("stock.inventory.kanban", readonly=True)
|
||||||
'stock.inventory.kanban',
|
|
||||||
readonly=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
def barcode_ending(self):
|
def barcode_ending(self):
|
||||||
super().barcode_ending()
|
super().barcode_ending()
|
||||||
self.inventory_kanban_id.write({
|
self.inventory_kanban_id.write({"scanned_kanban_ids": [(4, self.kanban_id.id)]})
|
||||||
'scanned_kanban_ids': [(4, self.kanban_id.id)]
|
|
||||||
})
|
|
||||||
|
|
||||||
def validate_kanban(self, barcode):
|
def validate_kanban(self, barcode):
|
||||||
res = super().validate_kanban(barcode)
|
res = super().validate_kanban(barcode)
|
||||||
|
|||||||
@@ -1,51 +1,56 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0" ?>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Copyright 2017 Eficent Business and IT Consulting Services, S.L.
|
Copyright 2017-2020 ForgeFlow, S.L.
|
||||||
Copyright 2017 Creu Blanca
|
Copyright 2017 Creu Blanca
|
||||||
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record id="wizard_stock_inventory_kanban_form" model="ir.ui.view">
|
<record id="wizard_stock_inventory_kanban_form" model="ir.ui.view">
|
||||||
<field name="name">wizard.stock.inventory.kanban.form</field>
|
<field name="name">wizard.stock.inventory.kanban.form</field>
|
||||||
<field name="model">wizard.stock.inventory.kanban</field>
|
<field name="model">wizard.stock.inventory.kanban</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Add Kanban">
|
<form string="Add Kanban">
|
||||||
<div class="alert alert-success text-center o_form_header"
|
<div
|
||||||
role="alert" style="margin-bottom:0px;"
|
class="alert alert-success text-center o_form_header"
|
||||||
attrs="{'invisible':[('status_state', '!=', 0)]}">
|
role="alert"
|
||||||
<bold><field name="status"/></bold>
|
style="margin-bottom:0px;"
|
||||||
|
attrs="{'invisible':[('status_state', '!=', 0)]}"
|
||||||
|
>
|
||||||
|
<bold>
|
||||||
|
<field name="status" />
|
||||||
|
</bold>
|
||||||
</div>
|
</div>
|
||||||
<div class="alert alert-danger alert-dismissable text-center"
|
<div
|
||||||
role="alert" style="margin-bottom:0px;"
|
class="alert alert-danger alert-dismissable text-center"
|
||||||
attrs="{'invisible':[('status_state', '=', 0)]}">
|
role="alert"
|
||||||
<bold><field name="status"/></bold>
|
style="margin-bottom:0px;"
|
||||||
|
attrs="{'invisible':[('status_state', '=', 0)]}"
|
||||||
|
>
|
||||||
|
<bold>
|
||||||
|
<field name="status" />
|
||||||
|
</bold>
|
||||||
</div>
|
</div>
|
||||||
<field name="status_state" invisible="1"/>
|
<field name="status_state" invisible="1" />
|
||||||
<field name="kanban_id" invisible="1"/>
|
<field name="kanban_id" invisible="1" />
|
||||||
<field name="inventory_kanban_id" invisible="1"/>
|
<field name="inventory_kanban_id" invisible="1" />
|
||||||
<field name="_barcode_scanned" widget="barcode_handler"
|
<field name="_barcode_scanned" widget="barcode_handler" />
|
||||||
invisible="1"/>
|
|
||||||
<footer>
|
<footer>
|
||||||
<button
|
<button
|
||||||
name="action_cancel"
|
name="action_cancel"
|
||||||
string="Close"
|
string="Close"
|
||||||
class="oe_link"
|
class="oe_link"
|
||||||
special="cancel"
|
special="cancel"
|
||||||
/>
|
/>
|
||||||
</footer>
|
</footer>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
<act_window
|
||||||
<act_window id="wizard_stock_inventory_kanban_action"
|
id="wizard_stock_inventory_kanban_action"
|
||||||
name="Add Kanban"
|
name="Add Kanban"
|
||||||
res_model="wizard.stock.inventory.kanban"
|
res_model="wizard.stock.inventory.kanban"
|
||||||
view_mode="form"
|
view_mode="form"
|
||||||
view_type="form"
|
context="{'default_inventory_kanban_id': active_id}"
|
||||||
context="{'default_inventory_kanban_id': active_id}"
|
target="new"
|
||||||
target="new"/>
|
/>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -1,44 +1,51 @@
|
|||||||
# Copyright 2017 Creu Blanca
|
# Copyright 2017 Creu Blanca
|
||||||
# Copyright 2017 Eficent Business and IT Consulting Services, S.L.
|
# Copyright 2017-2020 ForgeFlow, S.L.
|
||||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
from odoo import fields, models, _
|
from odoo import _, fields, models
|
||||||
|
|
||||||
|
|
||||||
class WizardStockRequestOrderKanbanAbstract(models.TransientModel):
|
class WizardStockRequestKanban(models.TransientModel):
|
||||||
_name = "wizard.stock.request.kanban"
|
_name = "wizard.stock.request.kanban"
|
||||||
|
_description = "Stock Request Kanban Wizard"
|
||||||
_inherit = "wizard.stock.request.kanban.abstract"
|
_inherit = "wizard.stock.request.kanban.abstract"
|
||||||
|
|
||||||
stock_request_id = fields.Many2one(
|
stock_request_id = fields.Many2one("stock.request", readonly=True)
|
||||||
'stock.request',
|
|
||||||
readonly=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
def barcode_ending(self):
|
def barcode_ending(self):
|
||||||
super().barcode_ending()
|
super().barcode_ending()
|
||||||
self.stock_request_id = self.env['stock.request'].create(
|
self.stock_request_id = self.env["stock.request"].create(
|
||||||
self.stock_request_kanban_values()
|
self.stock_request_kanban_values()
|
||||||
)
|
)
|
||||||
self.status_state = 0
|
|
||||||
self.status = _('Added kanban %s for product %s' % (
|
|
||||||
self.stock_request_id.kanban_id.name,
|
|
||||||
self.stock_request_id.product_id.display_name
|
|
||||||
))
|
|
||||||
self.stock_request_ending()
|
self.stock_request_ending()
|
||||||
|
self.update_status()
|
||||||
|
|
||||||
def stock_request_ending(self):
|
def stock_request_ending(self):
|
||||||
self.stock_request_id.action_confirm()
|
self.stock_request_id.action_confirm()
|
||||||
|
|
||||||
|
def update_status(self):
|
||||||
|
self.update(
|
||||||
|
{
|
||||||
|
"status_state": 0,
|
||||||
|
"status": _(
|
||||||
|
"Added kanban %s for product %s"
|
||||||
|
% (
|
||||||
|
self.stock_request_id.kanban_id.name,
|
||||||
|
self.stock_request_id.product_id.display_name,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
def stock_request_kanban_values(self):
|
def stock_request_kanban_values(self):
|
||||||
return {
|
return {
|
||||||
'company_id': self.kanban_id.company_id.id,
|
"company_id": self.kanban_id.company_id.id,
|
||||||
'procurement_group_id':
|
"procurement_group_id": self.kanban_id.procurement_group_id.id or False,
|
||||||
self.kanban_id.procurement_group_id.id or False,
|
"location_id": self.kanban_id.location_id.id or False,
|
||||||
'location_id': self.kanban_id.location_id.id or False,
|
"warehouse_id": self.kanban_id.warehouse_id.id or False,
|
||||||
'warehouse_id': self.kanban_id.warehouse_id.id or False,
|
"product_id": self.kanban_id.product_id.id,
|
||||||
'product_id': self.kanban_id.product_id.id,
|
"product_uom_id": self.kanban_id.product_uom_id.id or False,
|
||||||
'product_uom_id': self.kanban_id.product_uom_id.id or False,
|
"route_id": self.kanban_id.route_id.id or False,
|
||||||
'route_id': self.kanban_id.route_id.id or False,
|
"product_uom_qty": self.kanban_id.product_uom_qty,
|
||||||
'product_uom_qty': self.kanban_id.product_uom_qty,
|
"kanban_id": self.kanban_id.id,
|
||||||
'kanban_id': self.kanban_id.id,
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,47 +1,44 @@
|
|||||||
# Copyright 2017 Creu Blanca
|
# Copyright 2017 Creu Blanca
|
||||||
# Copyright 2017 Eficent Business and IT Consulting Services, S.L.
|
# Copyright 2017-2020 ForgeFlow, S.L.
|
||||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
from odoo import fields, models, _
|
from odoo import _, fields, models
|
||||||
|
|
||||||
|
|
||||||
class WizardStockRequestOrderKanbanAbstract(models.AbstractModel):
|
class WizardStockRequestKanbanAbstract(models.AbstractModel):
|
||||||
_name = "wizard.stock.request.kanban.abstract"
|
_name = "wizard.stock.request.kanban.abstract"
|
||||||
|
_description = "Stock Request Kanban Abstract Wizard"
|
||||||
_inherit = "barcodes.barcode_events_mixin"
|
_inherit = "barcodes.barcode_events_mixin"
|
||||||
|
|
||||||
kanban_id = fields.Many2one(
|
kanban_id = fields.Many2one("stock.request.kanban", readonly=True)
|
||||||
'stock.request.kanban',
|
status = fields.Text(readonly=True, default="Start scanning")
|
||||||
readonly=True,
|
status_state = fields.Integer(default=0, readonly=True)
|
||||||
)
|
|
||||||
status = fields.Text(
|
|
||||||
readonly=True,
|
|
||||||
default="Start scanning",
|
|
||||||
)
|
|
||||||
status_state = fields.Integer(
|
|
||||||
default=0,
|
|
||||||
readonly=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
def on_barcode_scanned(self, barcode):
|
def on_barcode_scanned(self, barcode):
|
||||||
self.kanban_id = self.env['stock.request.kanban'].search_barcode(
|
self.kanban_id = self.env["stock.request.kanban"].search_barcode(barcode)
|
||||||
barcode)
|
|
||||||
if not self.kanban_id:
|
if not self.kanban_id:
|
||||||
self.status = _("Barcode %s does not correspond to any "
|
self.status = (
|
||||||
"Kanban. Try with another barcode or "
|
_(
|
||||||
"press Close to finish scanning.") % barcode
|
"Barcode %s does not correspond to any "
|
||||||
|
"Kanban. Try with another barcode or "
|
||||||
|
"press Close to finish scanning."
|
||||||
|
)
|
||||||
|
% barcode
|
||||||
|
)
|
||||||
self.status_state = 1
|
self.status_state = 1
|
||||||
return
|
return
|
||||||
if self.validate_kanban(barcode):
|
if self.validate_kanban(barcode):
|
||||||
self.status_state = 0
|
self.status_state = 0
|
||||||
self.barcode_ending()
|
self.barcode_ending()
|
||||||
|
return
|
||||||
|
|
||||||
def barcode_ending(self):
|
def barcode_ending(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def validate_kanban(self, barcode):
|
def validate_kanban(self, barcode):
|
||||||
'''
|
"""
|
||||||
It must return True if the kanban is valid, False otherwise
|
It must return True if the kanban is valid, False otherwise
|
||||||
:param barcode:
|
:param barcode:
|
||||||
:return:
|
:return:
|
||||||
'''
|
"""
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -1,50 +1,55 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0" ?>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Copyright 2017 Eficent Business and IT Consulting Services, S.L.
|
Copyright 2017-2020 ForgeFlow, S.L.
|
||||||
Copyright 2017 Creu Blanca
|
Copyright 2017 Creu Blanca
|
||||||
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record id="wizard_stock_request_kanban_form" model="ir.ui.view">
|
<record id="wizard_stock_request_kanban_form" model="ir.ui.view">
|
||||||
<field name="name">wizard.stock.request.kanban.form</field>
|
<field name="name">wizard.stock.request.kanban.form</field>
|
||||||
<field name="model">wizard.stock.request.kanban</field>
|
<field name="model">wizard.stock.request.kanban</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Add Kanban">
|
<form string="Add Kanban">
|
||||||
<div class="alert alert-success text-center o_form_header"
|
<div
|
||||||
role="alert" style="margin-bottom:0px;"
|
class="alert alert-success text-center o_form_header"
|
||||||
attrs="{'invisible':[('status_state', '!=', 0)]}">
|
role="alert"
|
||||||
<bold><field name="status"/></bold>
|
style="margin-bottom:0px;"
|
||||||
|
attrs="{'invisible':[('status_state', '!=', 0)]}"
|
||||||
|
>
|
||||||
|
<bold>
|
||||||
|
<field name="status" />
|
||||||
|
</bold>
|
||||||
</div>
|
</div>
|
||||||
<div class="alert alert-danger alert-dismissable text-center"
|
<div
|
||||||
role="alert" style="margin-bottom:0px;"
|
class="alert alert-danger alert-dismissable text-center"
|
||||||
attrs="{'invisible':[('status_state', '=', 0)]}">
|
role="alert"
|
||||||
<bold><field name="status"/></bold>
|
style="margin-bottom:0px;"
|
||||||
|
attrs="{'invisible':[('status_state', '=', 0)]}"
|
||||||
|
>
|
||||||
|
<bold>
|
||||||
|
<field name="status" />
|
||||||
|
</bold>
|
||||||
</div>
|
</div>
|
||||||
<field name="status_state" invisible="1"/>
|
<field name="status_state" invisible="1" />
|
||||||
<field name="kanban_id" invisible="1"/>
|
<field name="kanban_id" invisible="1" />
|
||||||
<field name="stock_request_id" invisible="1"/>
|
<field name="stock_request_id" invisible="1" />
|
||||||
<field name="_barcode_scanned" widget="barcode_handler"
|
<field name="_barcode_scanned" widget="barcode_handler" />
|
||||||
invisible="1"/>
|
|
||||||
<footer>
|
<footer>
|
||||||
<button
|
<button
|
||||||
name="action_cancel"
|
name="action_cancel"
|
||||||
string="Close"
|
string="Close"
|
||||||
class="oe_link"
|
class="oe_link"
|
||||||
special="cancel"
|
special="cancel"
|
||||||
/>
|
/>
|
||||||
</footer>
|
</footer>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
<act_window
|
||||||
<act_window id="wizard_stock_request_kanban_action"
|
id="wizard_stock_request_kanban_action"
|
||||||
name="Add Kanban"
|
name="Add Kanban"
|
||||||
res_model="wizard.stock.request.kanban"
|
res_model="wizard.stock.request.kanban"
|
||||||
view_mode="form"
|
view_mode="form"
|
||||||
view_type="form"
|
target="new"
|
||||||
target="new"/>
|
/>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
# Copyright 2017 Creu Blanca
|
# Copyright 2017 Creu Blanca
|
||||||
# Copyright 2017 Eficent Business and IT Consulting Services, S.L.
|
# Copyright 2017-2020 ForgeFlow, S.L.
|
||||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
|
|
||||||
from odoo import fields, models, _
|
from odoo import _, fields, models
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
|
|
||||||
class WizardStockRequestOrderKanban(models.TransientModel):
|
class WizardStockRequestOrderKanban(models.TransientModel):
|
||||||
_name = "wizard.stock.request.order.kanban"
|
_name = "wizard.stock.request.order.kanban"
|
||||||
|
_description = "Stock Request Order Kanban Wizard"
|
||||||
_inherit = "wizard.stock.request.kanban"
|
_inherit = "wizard.stock.request.kanban"
|
||||||
|
|
||||||
order_id = fields.Many2one(
|
order_id = fields.Many2one("stock.request.order", required=True)
|
||||||
'stock.request.order',
|
|
||||||
required=True
|
|
||||||
)
|
|
||||||
|
|
||||||
def validate_kanban(self, barcode):
|
def validate_kanban(self, barcode):
|
||||||
res = super().validate_kanban(barcode)
|
res = super().validate_kanban(barcode)
|
||||||
@@ -23,30 +21,30 @@ class WizardStockRequestOrderKanban(models.TransientModel):
|
|||||||
self.status = _("Barcode %s is on the order") % barcode
|
self.status = _("Barcode %s is on the order") % barcode
|
||||||
self.status_state = 1
|
self.status_state = 1
|
||||||
return False
|
return False
|
||||||
if self.order_id.state != 'draft':
|
if self.order_id.state != "draft":
|
||||||
raise ValidationError(_(
|
raise ValidationError(
|
||||||
'Lines only can be added on orders with draft state'))
|
_("Lines only can be added on orders with draft state")
|
||||||
|
)
|
||||||
if not self.order_id.company_id:
|
if not self.order_id.company_id:
|
||||||
self.order_id.company_id = self.kanban_id.company_id
|
self.order_id.company_id = self.kanban_id.company_id
|
||||||
elif self.order_id.company_id != self.kanban_id.company_id:
|
elif self.order_id.company_id != self.kanban_id.company_id:
|
||||||
raise ValidationError(_('Company must be the same'))
|
raise ValidationError(_("Company must be the same"))
|
||||||
if (
|
if (
|
||||||
self.kanban_id.procurement_group_id and
|
self.kanban_id.procurement_group_id
|
||||||
self.order_id.procurement_group_id !=
|
and self.order_id.procurement_group_id
|
||||||
self.kanban_id.procurement_group_id
|
!= self.kanban_id.procurement_group_id
|
||||||
):
|
):
|
||||||
raise ValidationError(_('Procurement group must be the same'))
|
raise ValidationError(_("Procurement group must be the same"))
|
||||||
if self.order_id.location_id != self.kanban_id.location_id:
|
if self.order_id.location_id != self.kanban_id.location_id:
|
||||||
raise ValidationError(_('Location must be the same'))
|
raise ValidationError(_("Location must be the same"))
|
||||||
if self.order_id.warehouse_id != self.kanban_id.warehouse_id:
|
if self.order_id.warehouse_id != self.kanban_id.warehouse_id:
|
||||||
raise ValidationError(_('Warehouse must be the same'))
|
raise ValidationError(_("Warehouse must be the same"))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def stock_request_kanban_values(self):
|
def stock_request_kanban_values(self):
|
||||||
res = super().stock_request_kanban_values()
|
res = super().stock_request_kanban_values()
|
||||||
res['order_id'] = self.order_id.id,
|
res["order_id"] = (self.order_id.id,)
|
||||||
res['expected_date'] = \
|
res["expected_date"] = fields.Datetime.to_string(self.order_id.expected_date)
|
||||||
fields.Datetime.to_string(self.order_id.expected_date),
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def stock_request_ending(self):
|
def stock_request_ending(self):
|
||||||
|
|||||||
@@ -1,31 +1,27 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0" ?>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Copyright 2017 Eficent Business and IT Consulting Services, S.L.
|
Copyright 2017-2020 ForgeFlow, S.L.
|
||||||
Copyright 2017 Creu Blanca
|
Copyright 2017 Creu Blanca
|
||||||
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record id="wizard_stock_request_order_kanban_form" model="ir.ui.view">
|
<record id="wizard_stock_request_order_kanban_form" model="ir.ui.view">
|
||||||
<field name="name">wizard.stock.request.order.kanban.form</field>
|
<field name="name">wizard.stock.request.order.kanban.form</field>
|
||||||
<field name="model">wizard.stock.request.order.kanban</field>
|
<field name="model">wizard.stock.request.order.kanban</field>
|
||||||
<field name="mode">primary</field>
|
<field name="mode">primary</field>
|
||||||
<field name="inherit_id" ref="wizard_stock_request_kanban_form"/>
|
<field name="inherit_id" ref="wizard_stock_request_kanban_form" />
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<field name="kanban_id" position="after">
|
<field name="kanban_id" position="after">
|
||||||
<field name="order_id" invisible="1"/>
|
<field name="order_id" invisible="1" />
|
||||||
</field>
|
</field>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
<act_window
|
||||||
<act_window id="wizard_stock_request_order_kanban_action"
|
id="wizard_stock_request_order_kanban_action"
|
||||||
name="Add Kanban"
|
name="Add Kanban"
|
||||||
res_model="wizard.stock.request.order.kanban"
|
res_model="wizard.stock.request.order.kanban"
|
||||||
view_mode="form"
|
view_mode="form"
|
||||||
view_type="form"
|
context="{'default_order_id': active_id}"
|
||||||
context="{'default_order_id': active_id}"
|
target="new"
|
||||||
target="new"/>
|
/>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
Reference in New Issue
Block a user