Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions deltatech_picking_transit/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,27 @@ Features:
.. contents::
:local:

Changelog
=========

18.0.0.0.15
-----------

- Setup on install: create a per-company transit stock location and, on
each warehouse, a two-step delivery operation type (with automatic
second transfer) and a two-step reception operation type, wired to the
warehouse main stock location and the transit location. Runs only at
install, so databases already using the module are not affected.
- The second transfer can now be created manually only after the first
transfer is validated, so the goods are actually in the transit
location.
- The second transfer now inherits the quantity actually moved to
transit, so the flow works even when the operator filled only the
"Quantity" field and left the "Demand" at 0.
- Fixed the ``is_transit_transfer`` and ``sub_location_existent``
computes to work on multi-record sets (no more singleton errors) and
removed the side effect from the compute method.

Bug Tracker
===========

Expand Down
1 change: 1 addition & 0 deletions deltatech_picking_transit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from . import models
from . import wizard
from .hooks import post_init_hook
3 changes: 2 additions & 1 deletion deltatech_picking_transit/__manifest__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Stock Auto Transfer",
"version": "18.0.0.0.14",
"version": "18.0.0.0.15",
"author": "Terrabit, Voicu Stefan",
"website": "https://www.terrabit.ro",
"category": "Warehouse",
Expand All @@ -14,6 +14,7 @@
"views/stock_picking_type_view.xml",
],
"development_status": "Beta",
"post_init_hook": "post_init_hook",
"maintainers": ["VoicuStefan2001"],
"images": ["static/description/main_screenshot.png"],
}
81 changes: 81 additions & 0 deletions deltatech_picking_transit/hooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# hooks.py

from odoo import _


def post_init_hook(env):
"""Set up the two-step transit configuration on a fresh install.

Runs only at install time (never on module update), so databases that
already use this module are left untouched. For every company it creates a
dedicated transit stock location and, on each of the company warehouses, a
two-step delivery operation type (with automatic second transfer) and a
two-step reception operation type, wired to the warehouse main stock
location and the transit location.
"""
for company in env["res.company"].search([]):
_setup_company_two_step_transit(env, company)


def _setup_company_two_step_transit(env, company):
Location = env["stock.location"].with_company(company)
PickingType = env["stock.picking.type"].with_company(company)

parent_location = env.ref("stock.stock_location_locations", raise_if_not_found=False)
transit_location = Location.create(
{
"name": _("2-Step Transit"),
"usage": "transit",
"location_id": parent_location.id if parent_location else False,
"company_id": company.id,
}
)

warehouses = env["stock.warehouse"].search([("company_id", "=", company.id)])
for warehouse in warehouses:
stock_location = warehouse.lot_stock_id

# Two-step delivery: warehouse stock -> transit, with automatic
# creation of the second (reception) transfer on validation.
if not _has_two_step_type(PickingType, warehouse, "delivery"):
PickingType.create(
{
"name": _("2-Step Delivery"),
"code": "internal",
"sequence_code": "2SD",
"warehouse_id": warehouse.id,
"company_id": company.id,
"default_location_src_id": stock_location.id,
"default_location_dest_id": transit_location.id,
"two_step_transfer_use": "delivery",
"auto_second_transfer": True,
}
)

# Two-step reception: transit -> warehouse stock.
if not _has_two_step_type(PickingType, warehouse, "reception"):
PickingType.create(
{
"name": _("2-Step Reception"),
"code": "internal",
"sequence_code": "2SR",
"warehouse_id": warehouse.id,
"company_id": company.id,
"default_location_src_id": transit_location.id,
"default_location_dest_id": stock_location.id,
"two_step_transfer_use": "reception",
}
)


def _has_two_step_type(PickingType, warehouse, use):
return bool(
PickingType.search(
[
("warehouse_id", "=", warehouse.id),
("code", "=", "internal"),
("two_step_transfer_use", "=", use),
],
limit=1,
)
)
61 changes: 40 additions & 21 deletions deltatech_picking_transit/models/stock_picking.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,16 @@ class StockPicking(models.Model):
)

def open_transfer_wizard(self):
self.ensure_one()
if self.second_transfer_created:
raise UserError(_("Second transfer already created."))
if self.state != "done":
raise UserError(
_(
"Validate this transfer first. The second transfer can only be "
"created after the goods have arrived in the transit location."
)
)
return {
"name": "Create Transfer",
"type": "ir.actions.act_window",
Expand Down Expand Up @@ -48,7 +56,7 @@ def create_second_transfer_wizard(self, final_dest_location_id, picking_type_id)
new_picking.action_confirm()
# new_picking.action_assign()
# new_picking.do_unreserve()
self.second_transfer_created = True
picking.second_transfer_created = True

message = _("This transfer was generated from %s.") % picking.name
new_picking.message_post(body=message)
Expand All @@ -62,15 +70,22 @@ def create_second_transfer_wizard(self, final_dest_location_id, picking_type_id)
return new_picking

def copy_move_lines(self, source_picking, target_picking):
for move in source_picking.move_ids_without_package:
move.sudo().copy(
{
"picking_id": target_picking.id,
"location_id": source_picking.location_dest_id.id,
"location_dest_id": target_picking.location_dest_id.id,
"state": "draft",
}
)
moves = source_picking.move_ids_without_package
if not moves:
return
default = {
"picking_id": target_picking.id,
"location_id": source_picking.location_dest_id.id,
"location_dest_id": target_picking.location_dest_id.id,
"state": "draft",
}
vals_list = moves.sudo().copy_data(default)
for move, vals in zip(moves, vals_list):
# the second transfer must move what actually arrived in transit:
# use the done quantity so the flow still works when the operator
# filled only the "Quantity" field and left the "Demand" at 0
vals["product_uom_qty"] = move.quantity or move.product_uom_qty
self.env["stock.move"].sudo().create(vals_list)

# @api.model
# def create(self, vals):
Expand All @@ -80,14 +95,15 @@ def copy_move_lines(self, source_picking, target_picking):
# # res.immediate_transfer = False
# return res

@api.depends("picking_type_id")
def _compute_sub_location_existent(self):
for record in self:
sub_location_usage = (
self.env["ir.config_parameter"]
.sudo()
.get_param(key="deltatech_picking_transit.use_sub_locations", default=False)
)
if sub_location_usage and self.picking_type_id.code == "internal":
if sub_location_usage and record.picking_type_id.code == "internal":
record.sub_location_existent = True
else:
record.sub_location_existent = False
Expand All @@ -104,18 +120,21 @@ def reassign_location(self):
if quants:
move_line.location_id = quants[0].location_id

@api.onchange("picking_type_id")
@api.depends("picking_type_id", "second_transfer_created")
def _compute_is_transit_transfer(self):
for record in self:
if self.second_transfer_created:
record.is_transit_transfer = False
return
if record.picking_type_id.code == "internal" and record.picking_type_id.two_step_transfer_use == "delivery":
record.is_transit_transfer = True
record.action_toggle_is_locked()
# record.immediate_transfer = False
else:
record.is_transit_transfer = False
record.is_transit_transfer = bool(
not record.second_transfer_created
and record.picking_type_id.code == "internal"
and record.picking_type_id.two_step_transfer_use == "delivery"
)

@api.onchange("picking_type_id")
def _onchange_picking_type_lock_transit(self):
# lock the transit transfer so the move lines cannot be edited before
# the second transfer is generated
if self.is_transit_transfer:
self.action_toggle_is_locked()

def button_validate(self):
for picking in self:
Expand Down
15 changes: 15 additions & 0 deletions deltatech_picking_transit/readme/HISTORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## 18.0.0.0.15

- Setup on install: create a per-company transit stock location and, on each
warehouse, a two-step delivery operation type (with automatic second transfer)
and a two-step reception operation type, wired to the warehouse main stock
location and the transit location. Runs only at install, so databases already
using the module are not affected.
- The second transfer can now be created manually only after the first transfer
is validated, so the goods are actually in the transit location.
- The second transfer now inherits the quantity actually moved to transit, so
the flow works even when the operator filled only the "Quantity" field and
left the "Demand" at 0.
- Fixed the `is_transit_transfer` and `sub_location_existent` computes to work
on multi-record sets (no more singleton errors) and removed the side effect
from the compute method.
42 changes: 34 additions & 8 deletions deltatech_picking_transit/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -396,31 +396,57 @@ <h1 class="title">Stock Auto Transfer</h1>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-1">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-2">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-3">Authors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-4">Maintainers</a></li>
<li><a class="reference internal" href="#changelog" id="toc-entry-1">Changelog</a><ul>
<li><a class="reference internal" href="#section-1" id="toc-entry-2">18.0.0.0.15</a></li>
</ul>
</li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-3">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-4">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-5">Authors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-6">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="changelog">
<h1><a class="toc-backref" href="#toc-entry-1">Changelog</a></h1>
<div class="section" id="section-1">
<h2><a class="toc-backref" href="#toc-entry-2">18.0.0.0.15</a></h2>
<ul class="simple">
<li>Setup on install: create a per-company transit stock location and, on
each warehouse, a two-step delivery operation type (with automatic
second transfer) and a two-step reception operation type, wired to the
warehouse main stock location and the transit location. Runs only at
install, so databases already using the module are not affected.</li>
<li>The second transfer can now be created manually only after the first
transfer is validated, so the goods are actually in the transit
location.</li>
<li>The second transfer now inherits the quantity actually moved to
transit, so the flow works even when the operator filled only the
“Quantity” field and left the “Demand” at 0.</li>
<li>Fixed the <tt class="docutils literal">is_transit_transfer</tt> and <tt class="docutils literal">sub_location_existent</tt>
computes to work on multi-record sets (no more singleton errors) and
removed the side effect from the compute method.</li>
</ul>
</div>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-1">Bug Tracker</a></h1>
<h1><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://www.terrabit.ro/helpdesk">Terrabit Issues</a>.
In case of trouble, please check there if your issue has already been reported.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#toc-entry-2">Credits</a></h1>
<h1><a class="toc-backref" href="#toc-entry-4">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-3">Authors</a></h2>
<h2><a class="toc-backref" href="#toc-entry-5">Authors</a></h2>
<ul class="simple">
<li>Terrabit</li>
<li>Voicu Stefan</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-4">Maintainers</a></h2>
<h2><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h2>
<p>Current maintainer:</p>
<p><a class="reference external image-reference" href="https://github.com/VoicuStefan2001"><img alt="VoicuStefan2001" src="https://github.com/VoicuStefan2001.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/dhongu/deltatech/tree/18.0/deltatech_picking_transit">dhongu/deltatech</a> project on GitHub.</p>
Expand Down
2 changes: 1 addition & 1 deletion deltatech_picking_transit/views/stock_picking_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
type="object"
string="Create Transfer"
class="btn-primary"
invisible="is_transit_transfer==False or origin!=False or create_second_transfer_automatically==True"
invisible="is_transit_transfer==False or origin!=False or create_second_transfer_automatically==True or state!='done'"
/>
</xpath>
</field>
Expand Down
Loading