mirror of
https://github.com/bringout/oca-technical.git
synced 2026-04-21 12:12:08 +02:00
Initial commit: OCA Technical packages (595 packages)
This commit is contained in:
commit
2cc02aac6e
24950 changed files with 2318079 additions and 0 deletions
|
|
@ -0,0 +1,309 @@
|
|||
# Copyright 2017-20 ForgeFlow S.L. (https://www.forgeflow.com)
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
import json
|
||||
import logging
|
||||
from math import pi
|
||||
|
||||
from odoo import _, fields, models
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
try:
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from bokeh.embed import components
|
||||
from bokeh.models import DatetimeTickFormatter, HoverTool
|
||||
from bokeh.plotting import figure
|
||||
except (ImportError, IOError) as err:
|
||||
_logger.debug(err)
|
||||
|
||||
|
||||
class StockBuffer(models.Model):
|
||||
_inherit = "stock.buffer"
|
||||
|
||||
planning_history_chart = fields.Text(
|
||||
string="Historical Chart",
|
||||
compute="_compute_history_chart",
|
||||
)
|
||||
execution_history_chart = fields.Text(
|
||||
string="Execution Historical Chart",
|
||||
compute="_compute_execution_history_chart",
|
||||
)
|
||||
|
||||
def _prepare_history_data(self):
|
||||
self.ensure_one()
|
||||
data = {
|
||||
"buffer_id": self.id,
|
||||
"date": fields.Datetime.now(),
|
||||
"top_of_red": self.top_of_red,
|
||||
"top_of_yellow": self.top_of_yellow,
|
||||
"top_of_green": self.top_of_green,
|
||||
"net_flow_position": self.net_flow_position,
|
||||
"on_hand_position": self.product_location_qty_available_not_res,
|
||||
"adu": self.adu,
|
||||
}
|
||||
return data
|
||||
|
||||
def cron_actions(self, only_nfp=False):
|
||||
res = super().cron_actions(only_nfp=only_nfp)
|
||||
data = self._prepare_history_data()
|
||||
if not self.env.context.get("no_ddmrp_history"):
|
||||
self.env["ddmrp.history"].sudo().create(data)
|
||||
return res
|
||||
|
||||
def _compute_history_chart(self):
|
||||
def stacked(df, categories):
|
||||
areas = {}
|
||||
last = np.zeros(len(df[categories[0]]))
|
||||
for cat in categories:
|
||||
_next = last + df[cat]
|
||||
areas[cat] = np.hstack((last[::-1], _next))
|
||||
last = _next
|
||||
return areas
|
||||
|
||||
hex_colors = self._get_colors_hex_map(pallete="planning")
|
||||
planning_colors = [
|
||||
hex_colors["1_red"],
|
||||
hex_colors["2_yellow"],
|
||||
hex_colors["3_green"],
|
||||
]
|
||||
for rec in self:
|
||||
history = self.env["ddmrp.history"].search(
|
||||
[("buffer_id", "=", rec.id)], order="date"
|
||||
)
|
||||
if len(history) < 2:
|
||||
rec.planning_history_chart = json.dumps(
|
||||
{
|
||||
"div": _("Not enough data available."),
|
||||
"script": "",
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
N = len(history)
|
||||
categories = ["top_of_red", "top_of_yellow", "top_of_green"]
|
||||
data = {}
|
||||
|
||||
dates = [r.date for r in history]
|
||||
data["date"] = dates
|
||||
data[categories[0]] = [r.top_of_red for r in history]
|
||||
data[categories[1]] = [r.top_of_yellow - r.top_of_red for r in history]
|
||||
data[categories[2]] = [r.top_of_green - r.top_of_yellow for r in history]
|
||||
data["net_flow_position"] = [r.net_flow_position for r in history]
|
||||
data["on_hand_position"] = [r.on_hand_position for r in history]
|
||||
|
||||
df = pd.DataFrame(data)
|
||||
df = df.set_index(["date"])
|
||||
|
||||
areas = stacked(df, categories)
|
||||
|
||||
x2 = np.hstack((data["date"][::-1], data["date"]))
|
||||
|
||||
tops = [
|
||||
data[categories[0]][i] + data[categories[1]][i] + data[categories[2]][i]
|
||||
for i in range(N)
|
||||
] + [max(data["on_hand_position"]), max(data["net_flow_position"])]
|
||||
top_y = max(tops)
|
||||
min_y = min(
|
||||
[0, min(data["on_hand_position"]), min(data["net_flow_position"])]
|
||||
)
|
||||
if top_y <= min_y:
|
||||
top_y = min_y + 100
|
||||
p = figure(
|
||||
frame_height=400,
|
||||
x_range=(dates[0], dates[-1]),
|
||||
y_range=(min_y, top_y),
|
||||
x_axis_type="datetime",
|
||||
)
|
||||
p.sizing_mode = "stretch_width"
|
||||
p.toolbar.logo = None
|
||||
|
||||
p.grid.minor_grid_line_color = "#eeeeee"
|
||||
p.patches(
|
||||
[x2] * len(areas),
|
||||
[areas[cat] for cat in categories],
|
||||
color=planning_colors,
|
||||
alpha=0.8,
|
||||
line_color=None,
|
||||
)
|
||||
date_format = (
|
||||
self.env["res.lang"]._lang_get(self.env.lang or "en_US").date_format
|
||||
)
|
||||
p.xaxis.formatter = DatetimeTickFormatter(
|
||||
hours=date_format,
|
||||
days=date_format,
|
||||
months=date_format,
|
||||
years=date_format,
|
||||
)
|
||||
p.xaxis.major_label_orientation = pi / 4
|
||||
p.xaxis.axis_label_text_font = "helvetica"
|
||||
|
||||
unit = rec.product_uom.name
|
||||
hover = HoverTool(
|
||||
tooltips=[("qty", "$y %s" % unit)], point_policy="follow_mouse"
|
||||
)
|
||||
p.add_tools(hover)
|
||||
|
||||
p.line(dates, data["net_flow_position"], line_width=3)
|
||||
p.line(dates, data["on_hand_position"], line_width=3, line_dash="dotted")
|
||||
|
||||
script, div = components(p, wrap_script=False)
|
||||
json_data = json.dumps(
|
||||
{
|
||||
"div": div,
|
||||
"script": script,
|
||||
}
|
||||
)
|
||||
rec.planning_history_chart = json_data
|
||||
|
||||
def _compute_execution_history_chart(self):
|
||||
start_stack = 0
|
||||
|
||||
def stacked(df, categories):
|
||||
areas = {}
|
||||
last = np.zeros(len(df[categories[0]]))
|
||||
last += start_stack
|
||||
for cat in categories:
|
||||
_next = last + df[cat]
|
||||
areas[cat] = np.hstack((last[::-1], _next))
|
||||
last = _next
|
||||
return areas
|
||||
|
||||
hex_colors = self._get_colors_hex_map(pallete="execution")
|
||||
execution_colors = [
|
||||
hex_colors["0_dark_red"],
|
||||
hex_colors["1_red"],
|
||||
hex_colors["2_yellow"],
|
||||
hex_colors["3_green"],
|
||||
hex_colors["2_yellow"],
|
||||
hex_colors["1_red"],
|
||||
hex_colors["0_dark_red"],
|
||||
]
|
||||
history_model = self.env["ddmrp.history"]
|
||||
for rec in self:
|
||||
domain = [("buffer_id", "=", rec.id)]
|
||||
history_oh = history_model.search(
|
||||
domain, order="on_hand_position desc", limit=1
|
||||
)
|
||||
history_tog = history_model.search(
|
||||
domain + [("top_of_green", "!=", False)],
|
||||
order="top_of_green desc",
|
||||
limit=1,
|
||||
)
|
||||
finish_stack = max(history_oh.on_hand_position, history_tog.top_of_green)
|
||||
|
||||
history = history_model.search(
|
||||
domain, order="on_hand_position asc", limit=1
|
||||
)
|
||||
start_stack = history.on_hand_position
|
||||
if start_stack >= 0.0:
|
||||
start_stack = 0.0
|
||||
history = history_model.search(domain, order="date")
|
||||
if len(history) < 2:
|
||||
rec.execution_history_chart = json.dumps(
|
||||
{
|
||||
"div": _("Not enough data available."),
|
||||
"script": "",
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
N = len(history)
|
||||
|
||||
categories = [
|
||||
"dark_red_low",
|
||||
"top_of_red_low",
|
||||
"top_of_yellow_low",
|
||||
"top_of_green",
|
||||
"top_of_yellow",
|
||||
"top_of_red",
|
||||
"dark_red",
|
||||
]
|
||||
data = {}
|
||||
|
||||
dates = [r.date for r in history]
|
||||
data["date"] = dates
|
||||
data[categories[0]] = [(0 - start_stack) for r in history]
|
||||
data[categories[1]] = [(r.top_of_red / 2) for r in history]
|
||||
data[categories[2]] = [(r.top_of_red / 2) for r in history]
|
||||
data[categories[3]] = [r.top_of_green - r.top_of_yellow for r in history]
|
||||
data[categories[4]] = [
|
||||
(r.top_of_green - r.top_of_red - (r.top_of_green - r.top_of_yellow)) / 2
|
||||
for r in history
|
||||
]
|
||||
data[categories[5]] = [
|
||||
(r.top_of_green - r.top_of_red - (r.top_of_green - r.top_of_yellow)) / 2
|
||||
for r in history
|
||||
]
|
||||
data[categories[6]] = [
|
||||
finish_stack
|
||||
- r.top_of_red
|
||||
- (r.top_of_green - r.top_of_yellow)
|
||||
- (r.top_of_green - r.top_of_red - (r.top_of_green - r.top_of_yellow))
|
||||
for r in history
|
||||
]
|
||||
|
||||
data["on_hand_position"] = [r.on_hand_position for r in history]
|
||||
|
||||
df = pd.DataFrame(data)
|
||||
df = df.set_index(["date"])
|
||||
|
||||
areas = stacked(df, categories)
|
||||
|
||||
x2 = np.hstack((data["date"][::-1], data["date"]))
|
||||
|
||||
tops = [
|
||||
data[categories[0]][i]
|
||||
+ data[categories[1]][i]
|
||||
+ data[categories[2]][i]
|
||||
+ data[categories[3]][i]
|
||||
+ data[categories[4]][i]
|
||||
+ data[categories[5]][i]
|
||||
+ data[categories[6]][i]
|
||||
for i in range(N)
|
||||
]
|
||||
top_y = max(tops)
|
||||
p = figure(
|
||||
frame_height=400,
|
||||
x_range=(dates[0], dates[-1]),
|
||||
y_range=(start_stack, top_y or 100),
|
||||
x_axis_type="datetime",
|
||||
)
|
||||
p.sizing_mode = "stretch_width"
|
||||
p.toolbar.logo = None
|
||||
|
||||
p.grid.minor_grid_line_color = "#eeeeee"
|
||||
p.patches(
|
||||
[x2] * len(areas),
|
||||
[areas[cat] for cat in categories],
|
||||
color=execution_colors,
|
||||
alpha=0.8,
|
||||
line_color=None,
|
||||
)
|
||||
date_format = (
|
||||
self.env["res.lang"]._lang_get(self.env.lang or "en_US").date_format
|
||||
)
|
||||
p.xaxis.formatter = DatetimeTickFormatter(
|
||||
hours=date_format,
|
||||
days=date_format,
|
||||
months=date_format,
|
||||
years=date_format,
|
||||
)
|
||||
p.xaxis.major_label_orientation = pi / 4
|
||||
|
||||
unit = rec.product_uom.name
|
||||
hover = HoverTool(
|
||||
tooltips=[("qty", "$y %s" % unit)], point_policy="follow_mouse"
|
||||
)
|
||||
p.add_tools(hover)
|
||||
|
||||
p.line(dates, data["on_hand_position"], line_width=3, line_dash="dotted")
|
||||
|
||||
script, div = components(p, wrap_script=False)
|
||||
json_data = json.dumps(
|
||||
{
|
||||
"div": div,
|
||||
"script": script,
|
||||
}
|
||||
)
|
||||
rec.execution_history_chart = json_data
|
||||
Loading…
Add table
Add a link
Reference in a new issue