mirror of
https://github.com/bringout/oca-purchase.git
synced 2026-04-20 05:02:07 +02:00
Add oca-purchase submodule with 96 purchase modules moved from oca-workflow-process
🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
b0628ee8ea
commit
7378b233e9
3994 changed files with 334316 additions and 0 deletions
|
|
@ -0,0 +1,240 @@
|
|||
# Copyright 2018-2019 ForgeFlow, S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0)
|
||||
|
||||
from odoo import _, api, exceptions, fields, models
|
||||
|
||||
|
||||
class PurchaseOrder(models.Model):
|
||||
_inherit = "purchase.order"
|
||||
|
||||
def _purchase_request_confirm_message_content(self, request, request_dict=None):
|
||||
self.ensure_one()
|
||||
if not request_dict:
|
||||
request_dict = {}
|
||||
title = _("Order confirmation %(po_name)s for your Request %(pr_name)s") % {
|
||||
"po_name": self.name,
|
||||
"pr_name": request.name,
|
||||
}
|
||||
message = "<h3>%s</h3><ul>" % title
|
||||
message += _(
|
||||
"The following requested items from Purchase Request %(pr_name)s "
|
||||
"have now been confirmed in Purchase Order %(po_name)s:"
|
||||
) % {
|
||||
"po_name": self.name,
|
||||
"pr_name": request.name,
|
||||
}
|
||||
|
||||
for line in request_dict.values():
|
||||
message += _(
|
||||
"<li><b>%(prl_name)s</b>: Ordered quantity %(prl_qty)s %(prl_uom)s, "
|
||||
"Planned date %(prl_date_planned)s</li>"
|
||||
) % {
|
||||
"prl_name": line["name"],
|
||||
"prl_qty": line["product_qty"],
|
||||
"prl_uom": line["product_uom"],
|
||||
"prl_date_planned": line["date_planned"],
|
||||
}
|
||||
message += "</ul>"
|
||||
return message
|
||||
|
||||
def _purchase_request_confirm_message(self):
|
||||
request_obj = self.env["purchase.request"]
|
||||
for po in self:
|
||||
requests_dict = {}
|
||||
for line in po.order_line:
|
||||
for request_line in line.sudo().purchase_request_lines:
|
||||
request_id = request_line.request_id.id
|
||||
if request_id not in requests_dict:
|
||||
requests_dict[request_id] = {}
|
||||
date_planned = "%s" % line.date_planned
|
||||
data = {
|
||||
"name": request_line.name,
|
||||
"product_qty": line.product_qty,
|
||||
"product_uom": line.product_uom.name,
|
||||
"date_planned": date_planned,
|
||||
}
|
||||
requests_dict[request_id][request_line.id] = data
|
||||
for request_id in requests_dict:
|
||||
request = request_obj.sudo().browse(request_id)
|
||||
message = po._purchase_request_confirm_message_content(
|
||||
request, requests_dict[request_id]
|
||||
)
|
||||
request.message_post(
|
||||
body=message,
|
||||
subtype_id=self.env.ref(
|
||||
"purchase_request.mt_request_po_confirmed"
|
||||
).id,
|
||||
)
|
||||
return True
|
||||
|
||||
def _purchase_request_line_check(self):
|
||||
for po in self:
|
||||
for line in po.order_line:
|
||||
for request_line in line.purchase_request_lines:
|
||||
if request_line.sudo().purchase_state == "done":
|
||||
raise exceptions.UserError(
|
||||
_("Purchase Request %s has already been completed")
|
||||
% (request_line.request_id.name)
|
||||
)
|
||||
return True
|
||||
|
||||
def button_confirm(self):
|
||||
self._purchase_request_line_check()
|
||||
res = super(PurchaseOrder, self).button_confirm()
|
||||
self._purchase_request_confirm_message()
|
||||
return res
|
||||
|
||||
def unlink(self):
|
||||
alloc_to_unlink = self.env["purchase.request.allocation"]
|
||||
for rec in self:
|
||||
for alloc in (
|
||||
rec.order_line.mapped("purchase_request_lines")
|
||||
.mapped("purchase_request_allocation_ids")
|
||||
.filtered(
|
||||
lambda alloc, rec=rec: alloc.purchase_line_id.order_id.id == rec.id
|
||||
)
|
||||
):
|
||||
alloc_to_unlink += alloc
|
||||
res = super().unlink()
|
||||
alloc_to_unlink.unlink()
|
||||
return res
|
||||
|
||||
|
||||
class PurchaseOrderLine(models.Model):
|
||||
_inherit = "purchase.order.line"
|
||||
|
||||
purchase_request_lines = fields.Many2many(
|
||||
comodel_name="purchase.request.line",
|
||||
relation="purchase_request_purchase_order_line_rel",
|
||||
column1="purchase_order_line_id",
|
||||
column2="purchase_request_line_id",
|
||||
readonly=True,
|
||||
copy=False,
|
||||
)
|
||||
|
||||
purchase_request_allocation_ids = fields.One2many(
|
||||
comodel_name="purchase.request.allocation",
|
||||
inverse_name="purchase_line_id",
|
||||
string="Purchase Request Allocation",
|
||||
copy=False,
|
||||
)
|
||||
|
||||
def action_open_request_line_tree_view(self):
|
||||
"""
|
||||
:return dict: dictionary value for created view
|
||||
"""
|
||||
request_line_ids = []
|
||||
for line in self:
|
||||
request_line_ids += line.purchase_request_lines.ids
|
||||
|
||||
domain = [("id", "in", request_line_ids)]
|
||||
|
||||
return {
|
||||
"name": _("Purchase Request Lines"),
|
||||
"type": "ir.actions.act_window",
|
||||
"res_model": "purchase.request.line",
|
||||
"view_mode": "tree,form",
|
||||
"domain": domain,
|
||||
}
|
||||
|
||||
def _prepare_stock_moves(self, picking):
|
||||
self.ensure_one()
|
||||
val = super(PurchaseOrderLine, self)._prepare_stock_moves(picking)
|
||||
all_list = []
|
||||
for v in val:
|
||||
all_ids = self.env["purchase.request.allocation"].search(
|
||||
[("purchase_line_id", "=", v["purchase_line_id"])]
|
||||
)
|
||||
for all_id in all_ids:
|
||||
all_list.append((4, all_id.id))
|
||||
v["purchase_request_allocation_ids"] = all_list
|
||||
return val
|
||||
|
||||
def update_service_allocations(self, prev_qty_received):
|
||||
for rec in self:
|
||||
allocation = self.env["purchase.request.allocation"].search(
|
||||
[
|
||||
("purchase_line_id", "=", rec.id),
|
||||
("purchase_line_id.product_id.type", "=", "service"),
|
||||
]
|
||||
)
|
||||
if not allocation:
|
||||
return
|
||||
qty_left = rec.qty_received - prev_qty_received
|
||||
for alloc in allocation:
|
||||
allocated_product_qty = alloc.allocated_product_qty
|
||||
if not qty_left:
|
||||
alloc.purchase_request_line_id._compute_qty()
|
||||
break
|
||||
if alloc.open_product_qty <= qty_left:
|
||||
allocated_product_qty += alloc.open_product_qty
|
||||
qty_left -= alloc.open_product_qty
|
||||
alloc._notify_allocation(alloc.open_product_qty)
|
||||
else:
|
||||
allocated_product_qty += qty_left
|
||||
alloc._notify_allocation(qty_left)
|
||||
qty_left = 0
|
||||
alloc.write({"allocated_product_qty": allocated_product_qty})
|
||||
|
||||
message_data = self._prepare_request_message_data(
|
||||
alloc, alloc.purchase_request_line_id, allocated_product_qty
|
||||
)
|
||||
message = self._purchase_request_confirm_done_message_content(
|
||||
message_data
|
||||
)
|
||||
if message:
|
||||
alloc.purchase_request_line_id.request_id.message_post(
|
||||
body=message, subtype_id=self.env.ref("mail.mt_note").id
|
||||
)
|
||||
|
||||
alloc.purchase_request_line_id._compute_qty()
|
||||
return True
|
||||
|
||||
@api.model
|
||||
def _purchase_request_confirm_done_message_content(self, message_data):
|
||||
title = _("Service confirmation for Request %s") % (
|
||||
message_data["request_name"]
|
||||
)
|
||||
message = "<h3>%s</h3>" % title
|
||||
message += _(
|
||||
"The following requested services from Purchase"
|
||||
" Request %(request_name)s requested by %(requestor)s "
|
||||
"have now been received:"
|
||||
) % {
|
||||
"request_name": message_data["request_name"],
|
||||
"requestor": message_data["requestor"],
|
||||
}
|
||||
message += "<ul>"
|
||||
message += _(
|
||||
"<li><b>%(product_name)s</b>: "
|
||||
"Received quantity %(product_qty)s %(product_uom)s</li>"
|
||||
) % {
|
||||
"product_name": message_data["product_name"],
|
||||
"product_qty": message_data["product_qty"],
|
||||
"product_uom": message_data["product_uom"],
|
||||
}
|
||||
message += "</ul>"
|
||||
return message
|
||||
|
||||
def _prepare_request_message_data(self, alloc, request_line, allocated_qty):
|
||||
return {
|
||||
"request_name": request_line.request_id.name,
|
||||
"product_name": request_line.product_id.name_get()[0][1],
|
||||
"product_qty": allocated_qty,
|
||||
"product_uom": alloc.product_uom_id.name,
|
||||
"requestor": request_line.request_id.requested_by.partner_id.name,
|
||||
}
|
||||
|
||||
def write(self, vals):
|
||||
# As services do not generate stock move this tweak is required
|
||||
# to allocate them.
|
||||
prev_qty_received = {}
|
||||
if vals.get("qty_received", False):
|
||||
service_lines = self.filtered(lambda l: l.product_id.type == "service")
|
||||
for line in service_lines:
|
||||
prev_qty_received[line.id] = line.qty_received
|
||||
res = super(PurchaseOrderLine, self).write(vals)
|
||||
if prev_qty_received:
|
||||
for line in service_lines:
|
||||
line.update_service_allocations(prev_qty_received[line.id])
|
||||
return res
|
||||
Loading…
Add table
Add a link
Reference in a new issue