mirror of
https://gitlab.com/flectra-hq/flectra.git
synced 2026-08-19 01:34:43 -05:00
Merge branch 'master-upstream-patch-12102021' into 'master'
[PATCH] Upstream patch - 12102021 See merge request flectra-hq/flectra!459
This commit is contained in:
@@ -214,9 +214,9 @@ class AccountBankStatement(models.Model):
|
||||
reference = fields.Char(string='External Reference', states={'open': [('readonly', False)]}, copy=False, readonly=True, help="Used to hold the reference of the external mean that created this statement (name of imported file, reference of online synchronization...)")
|
||||
date = fields.Date(required=True, states={'confirm': [('readonly', True)]}, index=True, copy=False, default=fields.Date.context_today)
|
||||
date_done = fields.Datetime(string="Closed On")
|
||||
balance_start = fields.Monetary(string='Starting Balance', states={'confirm': [('readonly', True)]}, compute='_compute_starting_balance', readonly=False, store=True)
|
||||
balance_end_real = fields.Monetary('Ending Balance', states={'confirm': [('readonly', True)]}, compute='_compute_ending_balance', readonly=False, store=True)
|
||||
state = fields.Selection(string='Status', required=True, readonly=True, copy=False, selection=[
|
||||
balance_start = fields.Monetary(string='Starting Balance', states={'confirm': [('readonly', True)]}, compute='_compute_starting_balance', readonly=False, store=True, tracking=True)
|
||||
balance_end_real = fields.Monetary('Ending Balance', states={'confirm': [('readonly', True)]}, compute='_compute_ending_balance', readonly=False, store=True, tracking=True)
|
||||
state = fields.Selection(string='Status', required=True, readonly=True, copy=False, tracking=True, selection=[
|
||||
('open', 'New'),
|
||||
('posted', 'Processing'),
|
||||
('confirm', 'Validated'),
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
<field name="name">account.move.line.kanban</field>
|
||||
<field name="model">account.move.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban class="o_kanban_mobile" create="false">
|
||||
<kanban class="o_kanban_mobile" create="false" group_create="false">
|
||||
<field name="date_maturity"/>
|
||||
<field name="move_id"/>
|
||||
<field name="name"/>
|
||||
|
||||
@@ -1748,7 +1748,13 @@ class MrpProduction(models.Model):
|
||||
duplicates_unbuild = self.env['stock.move.line'].search_count(domain_unbuild + [
|
||||
('move_id.unbuild_id', '!=', False)
|
||||
])
|
||||
if not (duplicates_unbuild and duplicates - duplicates_unbuild == 0):
|
||||
removed = self.env['stock.move.line'].search_count([
|
||||
('lot_id', '=', move_line.lot_id.id),
|
||||
('state', '=', 'done'),
|
||||
('location_dest_id.scrap_location', '=', True)
|
||||
])
|
||||
# Either removed or unbuild
|
||||
if not ((duplicates_unbuild or removed) and duplicates - duplicates_unbuild - removed == 0):
|
||||
raise UserError(message)
|
||||
# Check presence of same sn in current production
|
||||
duplicates = co_prod_move_lines.filtered(lambda ml: ml.qty_done and ml.lot_id == move_line.lot_id) - move_line
|
||||
@@ -1784,7 +1790,13 @@ class MrpProduction(models.Model):
|
||||
duplicates_unbuild = self.env['stock.move.line'].search_count(domain_unbuild + [
|
||||
('move_id.unbuild_id', '!=', False)
|
||||
])
|
||||
if not (duplicates_unbuild and duplicates - duplicates_unbuild == 0):
|
||||
removed = self.env['stock.move.line'].search_count([
|
||||
('lot_id', '=', move_line.lot_id.id),
|
||||
('state', '=', 'done'),
|
||||
('location_dest_id.scrap_location', '=', True)
|
||||
])
|
||||
# Either removed or unbuild
|
||||
if not ((duplicates_unbuild or removed) and duplicates - duplicates_unbuild - removed == 0):
|
||||
raise UserError(message)
|
||||
# Check presence of same sn in current production
|
||||
duplicates = co_prod_move_lines.filtered(lambda ml: ml.qty_done and ml.lot_id == move_line.lot_id) - move_line
|
||||
|
||||
@@ -5,6 +5,8 @@ from flectra.tests import Form, tagged
|
||||
from flectra.addons.mrp.tests.common import TestMrpCommon
|
||||
import uuid
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestTraceability(TestMrpCommon):
|
||||
TRACKING_TYPES = ['none', 'serial', 'lot']
|
||||
|
||||
@@ -306,3 +308,83 @@ class TestTraceability(TestMrpCommon):
|
||||
self.assertEqual(byproduct_move_line_2_lot_1.consume_line_ids.filtered(lambda l: l.qty_done), raw_line_raw_1_lot_1 | raw_line_raw_2_lot_1)
|
||||
byproduct_move_line_2_lot_2 = finished_move_lines.filtered(lambda ml: ml.lot_id.name == 'Byproduct_2_lot_2')
|
||||
self.assertEqual(byproduct_move_line_2_lot_2.consume_line_ids, raw_line_raw_1_lot_2 | raw_line_raw_2_lot_2)
|
||||
|
||||
def test_tracking_repair_production(self):
|
||||
"""
|
||||
Test that removing a tracked component with a repair does not block the flow of using that component in another
|
||||
bom
|
||||
"""
|
||||
if 'repair.order' not in self.env: # Module required for that test
|
||||
return
|
||||
product_to_repair = self.env['product.product'].create({
|
||||
'name': 'product first serial to act repair',
|
||||
'tracking': 'serial',
|
||||
})
|
||||
ptrepair_lot = self.env['stock.production.lot'].create({
|
||||
'name': 'A1',
|
||||
'product_id': product_to_repair.id,
|
||||
'company_id': self.env.user.company_id.id
|
||||
})
|
||||
product_to_remove = self.env['product.product'].create({
|
||||
'name': 'other first serial to remove with repair',
|
||||
'tracking': 'serial',
|
||||
})
|
||||
ptremove_lot = self.env['stock.production.lot'].create({
|
||||
'name': 'B2',
|
||||
'product_id': product_to_remove.id,
|
||||
'company_id': self.env.user.company_id.id
|
||||
})
|
||||
# Create a manufacturing order with product (with SN A1)
|
||||
mo = self.env['mrp.production'].create({
|
||||
'name': 'testing',
|
||||
'product_id': product_to_repair.id,
|
||||
'product_uom_id': product_to_repair.uom_id.id,
|
||||
'product_qty': 1
|
||||
})
|
||||
mo_form = Form(mo)
|
||||
with mo_form.move_raw_ids.new() as move:
|
||||
move.product_id = product_to_remove
|
||||
move.product_uom_qty = 1
|
||||
move.move_line_ids.lot_id = ptremove_lot # Set component serial to B2
|
||||
mo = mo_form.save()
|
||||
mo.action_confirm()
|
||||
# Set serial to A1
|
||||
mo.lot_producing_id = ptrepair_lot
|
||||
mo.button_mark_done()
|
||||
|
||||
with Form(self.env['repair.order']) as ro_form:
|
||||
ro_form.name = 'Please repair'
|
||||
ro_form.product_id = product_to_repair
|
||||
ro_form.lot_id = ptrepair_lot # Repair product Serial A1
|
||||
with ro_form.operations.new() as operation:
|
||||
operation.type = 'remove'
|
||||
operation.product_id = product_to_remove
|
||||
operation.lot_id = ptremove_lot # Remove product Serial B2 from the product
|
||||
ro = ro_form.save()
|
||||
ro.action_validate()
|
||||
ro.action_repair_start()
|
||||
ro.action_repair_end()
|
||||
|
||||
# Create a manufacturing order with product (with SN A2)
|
||||
mo2 = self.env['mrp.production'].create({
|
||||
'name': 'testing duo',
|
||||
'product_id': product_to_repair.id,
|
||||
'product_uom_id': product_to_repair.uom_id.id,
|
||||
'product_qty': 1
|
||||
})
|
||||
mo2_form = Form(mo2)
|
||||
with mo2_form.move_raw_ids.new() as move:
|
||||
move.product_id = product_to_remove
|
||||
move.product_uom_qty = 1
|
||||
move.move_line_ids.lot_id = ptremove_lot # Set component serial to B2 again, it is possible
|
||||
mo2 = mo2_form.save()
|
||||
mo2.action_confirm()
|
||||
# Set serial to A2
|
||||
mo2.lot_producing_id = self.env['stock.production.lot'].create({
|
||||
'name': 'A2',
|
||||
'product_id': product_to_repair.id,
|
||||
'company_id': self.env.user.company_id.id
|
||||
})
|
||||
# We are not forbidden to use that serial number, so nothing raised here
|
||||
mo2.button_mark_done()
|
||||
|
||||
|
||||
@@ -166,6 +166,10 @@ flectra.define('web.CustomFilterItem', function (require) {
|
||||
val => field_utils.format[type](val, { type }, { timezone: false })
|
||||
);
|
||||
descriptionArray.push(`"${dateValue.join(" " + this.env._t("and") + " ")}"`);
|
||||
} else if (type === "selection") {
|
||||
domainValue = [condition.value];
|
||||
const formattedValue = field_utils.format[type](condition.value, field);
|
||||
descriptionArray.push(`"${formattedValue}"`);
|
||||
} else {
|
||||
domainValue = [condition.value];
|
||||
descriptionArray.push(`"${condition.value}"`);
|
||||
|
||||
@@ -91,7 +91,7 @@ flectra.define('web.filter_menu_generator_tests', function (require) {
|
||||
|
||||
// Default value
|
||||
expectedFilters = [{
|
||||
description: 'Color is "black"',
|
||||
description: 'Color is "Black"',
|
||||
domain: '[["color","=","black"]]',
|
||||
type: 'filter',
|
||||
}];
|
||||
@@ -101,7 +101,7 @@ flectra.define('web.filter_menu_generator_tests', function (require) {
|
||||
|
||||
// Updated value
|
||||
expectedFilters = [{
|
||||
description: 'Color is "white"',
|
||||
description: 'Color is "White"',
|
||||
domain: '[["color","=","white"]]',
|
||||
type: 'filter',
|
||||
}];
|
||||
|
||||
@@ -70,11 +70,10 @@
|
||||
<!-- Note: no need of extra dependency thanks to the apply-to -->
|
||||
</t>
|
||||
</div>
|
||||
<div data-selector=".s_product_catalog_dish"/>
|
||||
<div data-selector=".s_product_catalog_dish" data-drop-near=".s_product_catalog_dish"/>
|
||||
</xpath>
|
||||
<xpath expr="//div[@data-js='SnippetMove']" position="attributes">
|
||||
<attribute name="data-selector" add=".s_product_catalog_dish" separator=","/>
|
||||
<attribute name="data-drop-near" add=".s_product_catalog_dish" separator=","/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user