[IMP] stock : Improve general usability
Purchase - When a RFQ is in "To Approve" stage, on the printed pdf, keep "Request for Quotation" as a title - "Send Reminder" action should open the composer when triggered manually. Inventory - In tree view of transfer, set date_done optional = hide - In (mobile) picking view, replace button text with 'add a product' - fix Vendor Group by in Replenishment report - Warning message when changing product tracking from untracked to tracked MRP - Reporting > Manufacturing Orders : change measure for total quantity grouped by scheduled date = month and by product - Reporting > Work Orders : change measure for Duration per unit grouped by workcenter and by product & add unit (minutes) - Reporting > Overall equipment effectiveness : group by loss reason added to the current group by workcenter closes odoo/odoo#57036 Related: odoo/enterprise#12926 Signed-off-by: William Henrotin <Whenrow@users.noreply.github.com>
This commit is contained in:
@@ -448,8 +448,9 @@
|
||||
<field name="name">mrp.production.graph</field>
|
||||
<field name="model">mrp.production</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Manufacturing Orders" type="line" sample="1">
|
||||
<graph string="Manufacturing Orders" type="bar" stacked="False" sample="1">
|
||||
<field name="date_planned_finished"/>
|
||||
<field name="product_uom_qty" type="measure" />
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
@@ -555,6 +556,7 @@
|
||||
<field name="res_model">mrp.production</field>
|
||||
<field name="view_mode">graph,pivot,form</field>
|
||||
<field name="target">current</field>
|
||||
<field name="context">{'search_default_scheduled_date': 1, 'search_default_product': 2, 'default_company_id': allowed_company_ids[0]}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
No data yet!
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Workcenter Productivity" type="pie" sample="1">
|
||||
<field name="loss_id"/>
|
||||
<field name="duration" type="measure"/>
|
||||
<field name="duration" type="measure" string="Duration (minutes)"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
@@ -125,7 +125,7 @@
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">mrp.workorder</field>
|
||||
<field name="domain">[]</field>
|
||||
<field name="context">{'search_default_done': True}</field>
|
||||
<field name="context">{'search_default_workcenter': 1, 'search_default_product': 2}</field>
|
||||
<field name="view_mode">graph,pivot,tree,form,gantt</field>
|
||||
<field name="search_view_id" ref="view_mrp_production_work_order_search"/>
|
||||
<field name="help" type="html">
|
||||
@@ -566,7 +566,7 @@
|
||||
<graph string="Workcenter Productivity" sample="1">
|
||||
<field name="workcenter_id"/>
|
||||
<field name="loss_id"/>
|
||||
<field name="duration" type="measure"/>
|
||||
<field name="duration" type="measure" string="Duration (minutes)"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
@@ -578,7 +578,7 @@
|
||||
<pivot string="Workcenter Productivity" sample="1">
|
||||
<field name="date_start" type="row" interval="day"/>
|
||||
<field name="loss_type" type="col"/>
|
||||
<field name="duration" type="measure"/>
|
||||
<field name="duration" type="measure" string="Duration (minutes)"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
@@ -589,7 +589,7 @@
|
||||
<field name="res_model">mrp.workcenter.productivity</field>
|
||||
<field name="view_mode">graph,pivot,tree,form</field>
|
||||
<field name="domain">[]</field>
|
||||
<field name="context">{'search_default_workcenter_group': 1, 'search_default_thismonth':True, 'create':False,'edit':False}</field>
|
||||
<field name="context">{'search_default_workcenter_group': 1, 'search_default_loss_group': 2, 'create':False,'edit':False}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Overall Equipment Effectiveness: no working or blocked time
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
<filter string="Late" name="late" domain="[('date_planned_start','<=',time.strftime('%%Y-%%m-%%d'))]"/>
|
||||
<separator/>
|
||||
<filter string="Start Date" name="date_start_filter" date="date_start"/>
|
||||
<group expand="0" string="Group By...">
|
||||
<filter string="Work center" name="workcenter" domain="[]" context="{'group_by': 'workcenter_id'}"/>
|
||||
<filter string="Product" name="product" domain="[]" context="{'group_by': 'product_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
@@ -257,9 +261,11 @@
|
||||
<field name="name">mrp.production.work.order.graph</field>
|
||||
<field name="model">mrp.workorder</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Operations" sample="1">
|
||||
<graph string="Operations" type="bar" stacked="False" sample="1">
|
||||
<field name="production_id"/>
|
||||
<field name="duration" type="measure"/>
|
||||
<field name="duration" type="measure" string="Duration (minutes)"/>
|
||||
<field name="duration_unit" type="measure"/>
|
||||
<field name="duration_expected" type="measure"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
@@ -271,7 +277,8 @@
|
||||
<pivot string="Operations" sample="1">
|
||||
<field name="date_start"/>
|
||||
<field name="operation_id"/>
|
||||
<field name="duration" type="measure"/>
|
||||
<field name="duration" type="measure" string="Duration (minutes)"/>
|
||||
<field name="duration_unit" type="measure"/>
|
||||
<field name="duration_expected" type="measure"/>
|
||||
</pivot>
|
||||
</field>
|
||||
@@ -470,7 +477,7 @@
|
||||
<field name="model">mrp.workorder</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Work Center Loads" sample="1">
|
||||
<field name="duration_expected" type="measure"/>
|
||||
<field name="duration_expected" type="measure" string="Expected Duration (minutes)"/>
|
||||
<field name="workcenter_id" type="row"/>
|
||||
<field name="production_date" type="row" interval="day"/>
|
||||
</pivot>
|
||||
@@ -484,7 +491,7 @@
|
||||
<graph string="Work Center load" type="bar" sample="1">
|
||||
<field name="production_date" interval="day"/>
|
||||
<field name="workcenter_id"/>
|
||||
<field name="duration_expected" type="measure"/>
|
||||
<field name="duration_expected" type="measure" string="Expected Duration (minutes)"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -660,7 +660,10 @@ class PurchaseOrder(models.Model):
|
||||
for order in orders:
|
||||
date = order.date_planned
|
||||
if date and (send_single or (date - relativedelta(days=order.reminder_date_before_receipt)).date() == datetime.today().date()):
|
||||
order.with_context(is_reminder=True).message_post_with_template(template.id, email_layout_xmlid="mail.mail_notification_paynow", composition_mode='comment')
|
||||
if send_single:
|
||||
return order._send_reminder_open_composer(template.id)
|
||||
else:
|
||||
order.with_context(is_reminder=True).message_post_with_template(template.id, email_layout_xmlid="mail.mail_notification_paynow", composition_mode='comment')
|
||||
|
||||
def send_reminder_preview(self):
|
||||
self.ensure_one()
|
||||
@@ -677,6 +680,43 @@ class PurchaseOrder(models.Model):
|
||||
notif_layout="mail.mail_notification_paynow")
|
||||
return {'toast_message': _("A sample email has been sent to %s.") % self.env.user.email}
|
||||
|
||||
def _send_reminder_open_composer(self,template_id):
|
||||
self.ensure_one()
|
||||
try:
|
||||
compose_form_id = self.env['ir.model.data'].get_object_reference('mail', 'email_compose_message_wizard_form')[1]
|
||||
except ValueError:
|
||||
compose_form_id = False
|
||||
ctx = dict(self.env.context or {})
|
||||
ctx.update({
|
||||
'default_model': 'purchase.order',
|
||||
'active_model': 'purchase.order',
|
||||
'active_id': self.ids[0],
|
||||
'default_res_id': self.ids[0],
|
||||
'default_use_template': bool(template_id),
|
||||
'default_template_id': template_id,
|
||||
'default_composition_mode': 'comment',
|
||||
'custom_layout': "mail.mail_notification_paynow",
|
||||
'force_email': True,
|
||||
'mark_rfq_as_sent': True,
|
||||
})
|
||||
lang = self.env.context.get('lang')
|
||||
if {'default_template_id', 'default_model', 'default_res_id'} <= ctx.keys():
|
||||
template = self.env['mail.template'].browse(ctx['default_template_id'])
|
||||
if template and template.lang:
|
||||
lang = template._render_lang([ctx['default_res_id']])[ctx['default_res_id']]
|
||||
self = self.with_context(lang=lang)
|
||||
ctx['model_description'] = _('Purchase Order')
|
||||
return {
|
||||
'name': _('Compose Email'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_mode': 'form',
|
||||
'res_model': 'mail.compose.message',
|
||||
'views': [(compose_form_id, 'form')],
|
||||
'view_id': compose_form_id,
|
||||
'target': 'new',
|
||||
'context': ctx,
|
||||
}
|
||||
|
||||
@api.model
|
||||
def _get_orders_to_remind(self):
|
||||
"""When auto sending a reminder mail, only send for unconfirmed purchase
|
||||
|
||||
@@ -21,8 +21,7 @@
|
||||
<div class="page">
|
||||
<div class="oe_structure"/>
|
||||
|
||||
<h2 t-if="o.state == 'draft'">Request for Quotation #<span t-field="o.name"/></h2>
|
||||
<h2 t-if="o.state in ['sent', 'to approve']">Purchase Order #<span t-field="o.name"/></h2>
|
||||
<h2 t-if="o.state in ['draft', 'sent', 'to approve']">Request for Quotation #<span t-field="o.name"/></h2>
|
||||
<h2 t-if="o.state in ['purchase', 'done']">Purchase Order #<span t-field="o.name"/></h2>
|
||||
<h2 t-if="o.state == 'cancel'">Cancelled Purchase Order #<span t-field="o.name"/></h2>
|
||||
|
||||
|
||||
@@ -180,8 +180,9 @@ class Orderpoint(models.Model):
|
||||
|
||||
show_supplier = fields.Boolean('Show supplier column', compute='_compute_show_suppplier')
|
||||
supplier_id = fields.Many2one(
|
||||
'product.supplierinfo', string='Vendor', check_company=True,
|
||||
'product.supplierinfo', string='Product Supplier', check_company=True,
|
||||
domain="['|', ('product_id', '=', product_id), '&', ('product_id', '=', False), ('product_tmpl_id', '=', product_tmpl_id)]")
|
||||
vendor_id = fields.Many2one(related='supplier_id.name', string="Vendor", store=True)
|
||||
|
||||
@api.depends('product_id.purchase_order_line_ids', 'product_id.purchase_order_line_ids.state')
|
||||
def _compute_qty(self):
|
||||
|
||||
@@ -363,14 +363,11 @@ class Product(models.Model):
|
||||
|
||||
@api.onchange('tracking')
|
||||
def onchange_tracking(self):
|
||||
products = self.filtered(lambda self: self.tracking and self.tracking != 'none')
|
||||
if products:
|
||||
unassigned_quants = self.env['stock.quant'].search_count([('product_id', 'in', products.ids), ('lot_id', '=', False), ('location_id.usage','=', 'internal')])
|
||||
if unassigned_quants:
|
||||
return {
|
||||
'warning': {
|
||||
'title': _('Warning!'),
|
||||
'message': _("You have product(s) in stock that have no lot/serial number. You can assign lot/serial numbers by doing an inventory adjustment.")}}
|
||||
if self.tracking != "none" and self.qty_available > 0:
|
||||
return {
|
||||
'warning': {
|
||||
'title': _('Warning!'),
|
||||
'message': _("You have product(s) in stock that have no lot/serial number. You can assign lot/serial numbers by doing an inventory adjustment.")}}
|
||||
|
||||
@api.model
|
||||
def view_header_get(self, view_id, view_type):
|
||||
|
||||
@@ -185,6 +185,7 @@
|
||||
<field name="user_id" optional="hide" widget="many2one_avatar_user"/>
|
||||
<field name="scheduled_date" optional="show" widget="remaining_days" attrs="{'invisible':[('state', 'in', ('done', 'cancel'))]}"/>
|
||||
<field name="date_deadline" optional="hide" widget="remaining_days" attrs="{'invisible':[('state', 'in', ('done', 'cancel'))]}"/>
|
||||
<field name="date_done" string="Effective Date" optional="hide"/>
|
||||
<field name="origin" optional="show"/>
|
||||
<field name="group_id" invisible="1"/>
|
||||
<field name="backorder_id" optional="hide"/>
|
||||
@@ -334,7 +335,8 @@
|
||||
<page string="Operations" name="operations">
|
||||
<field name="move_ids_without_package" mode="tree,kanban"
|
||||
attrs="{'readonly': ['&', ('state', '=', 'done'), ('is_locked', '=', True)]}"
|
||||
context="{'default_company_id': company_id, 'default_date': scheduled_date, 'default_date_deadline': date_deadline, 'picking_type_code': picking_type_code, 'default_picking_id': id, 'form_view_ref':'stock.view_move_form', 'address_in_id': partner_id, 'default_picking_type_id': picking_type_id, 'default_location_id': location_id, 'default_location_dest_id': location_dest_id}">
|
||||
context="{'default_company_id': company_id, 'default_date': scheduled_date, 'default_date_deadline': date_deadline, 'picking_type_code': picking_type_code, 'default_picking_id': id, 'form_view_ref':'stock.view_move_form', 'address_in_id': partner_id, 'default_picking_type_id': picking_type_id, 'default_location_id': location_id, 'default_location_dest_id': location_dest_id}"
|
||||
options="{'create_text':'Add a Product'}">
|
||||
<tree decoration-danger="not parent.immediate_transfer and state != 'done' and quantity_done > reserved_availability and show_reserved_availability" decoration-muted="scrapped == True or state == 'cancel' or (state == 'done' and is_locked == True)" string="Stock Moves" editable="bottom">
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="name" invisible="1"/>
|
||||
@@ -644,7 +646,7 @@
|
||||
<field name="name">stock.picking.type.kanban</field>
|
||||
<field name="model">stock.picking.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban class="oe_background_grey o_kanban_dashboard o_emphasize_colors o_stock_kanban" create="0">
|
||||
<kanban class="oe_background_grey o_kanban_dashboard o_emphasize_colors o_stock_kanban" create="0" group_create="false">
|
||||
<field name="color"/>
|
||||
<field name="code" readonly="1"/>
|
||||
<field name="count_picking_ready"/>
|
||||
|
||||
Reference in New Issue
Block a user