[PATCH] Upstream patch - 14062023

This commit is contained in:
Parthiv Patel
2023-06-14 08:35:04 +00:00
parent ae927238b4
commit a1d4e42539
9 changed files with 148 additions and 12 deletions
+2 -2
View File
@@ -130,12 +130,12 @@ class Task(models.Model):
def _compute_effective_hours(self):
if not any(self._ids):
for task in self:
task.effective_hours = round(sum(task.timesheet_ids.mapped('unit_amount')), 2)
task.effective_hours = sum(task.timesheet_ids.mapped('unit_amount'))
return
timesheet_read_group = self.env['account.analytic.line'].read_group([('task_id', 'in', self.ids)], ['unit_amount', 'task_id'], ['task_id'])
timesheets_per_task = {res['task_id'][0]: res['unit_amount'] for res in timesheet_read_group}
for task in self:
task.effective_hours = round(timesheets_per_task.get(task.id, 0.0), 2)
task.effective_hours = timesheets_per_task.get(task.id, 0.0)
@api.depends('effective_hours', 'subtask_effective_hours', 'planned_hours')
def _compute_progress_hours(self):
@@ -499,3 +499,31 @@ class TestTimesheet(TestCommonTimesheet):
self.assertEqual(timesheet.product_uom_id, self.project_customer.company_id.project_time_mode_id,
"The product_uom_id of the timesheet should be equal to the project's company uom "
"if the project's analytic account has no company_id")
def test_percentage_of_planned_hours(self):
""" Test the percentage of planned hours on a task. """
self.task1.planned_hours = round(11/60, 2)
self.assertEqual(self.task1.effective_hours, 0, 'No timesheet should be created yet.')
self.assertEqual(self.task1.progress, 0, 'No timesheet should be created yet.')
self.env['account.analytic.line'].create([
{
'name': 'Timesheet',
'project_id': self.project_customer.id,
'task_id': self.task1.id,
'unit_amount': 3/60,
'employee_id': self.empl_employee.id,
}, {
'name': 'Timesheet',
'project_id': self.project_customer.id,
'task_id': self.task1.id,
'unit_amount': 4/60,
'employee_id': self.empl_employee.id,
}, {
'name': 'Timesheet',
'project_id': self.project_customer.id,
'task_id': self.task1.id,
'unit_amount': 4/60,
'employee_id': self.empl_employee.id,
},
])
self.assertEqual(self.task1.progress, 100, 'The percentage of planned hours should be 100%.')
+67
View File
@@ -3404,6 +3404,39 @@
}),
]"/>
</record>
<record id="account_tax_template_p_irpf24_rdc" model="account.tax.template">
<field name="type_tax_use">purchase</field>
<field name="name">Retenciones IRPF 24% (Rendimientos del capital)</field>
<field name="chart_template_id" ref="l10n_es.account_chart_template_common"/>
<field name="amount" eval="-24"/>
<field name="amount_type">percent</field>
<field name="tax_group_id" ref="tax_group_retenciones_24"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('l10n_es.account_common_4751'),
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('l10n_es.account_common_4751'),
}),
]"/>
</record>
<record id="account_tax_template_s_irpf20" model="account.tax.template">
<field name="description">Retención 20%</field>
<field name="type_tax_use">sale</field>
@@ -3506,6 +3539,40 @@
}),
]"/>
</record>
<record id="account_tax_template_s_irpf24_rdc" model="account.tax.template">
<field name="description">Retención 24% (Rendimientos del capital)</field>
<field name="type_tax_use">sale</field>
<field name="name">Retenciones a cuenta IRPF 24%</field>
<field name="chart_template_id" ref="l10n_es.account_chart_template_common"/>
<field name="amount" eval="-24"/>
<field name="amount_type">percent</field>
<field name="tax_group_id" ref="tax_group_retenciones_24"/>
<field name="invoice_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('l10n_es.account_common_473'),
}),
]"/>
<field name="refund_repartition_line_ids" eval="[(5, 0, 0),
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
}),
(0,0, {
'factor_percent': 100,
'repartition_type': 'tax',
'account_id': ref('l10n_es.account_common_473'),
}),
]"/>
</record>
<record id="account_tax_template_p_iva12_agr" model="account.tax.template">
<field name="description"/> <!-- for resetting the value on existing DBs -->
<field name="type_tax_use">purchase</field>
@@ -21,6 +21,7 @@ flectra.define('point_of_sale.ProductScreen', function(require) {
useListener('click-pay', this._onClickPay);
useBarcodeReader({
product: this._barcodeProductAction,
quantity: this._barcodeProductAction,
weight: this._barcodeProductAction,
price: this._barcodeProductAction,
client: this._barcodeClientAction,
@@ -221,7 +222,7 @@ flectra.define('point_of_sale.ProductScreen', function(require) {
price_manually_set: true,
},
});
} else if (code.type === 'weight') {
} else if (code.type === 'weight' || code.type === 'quantity') {
Object.assign(options, {
quantity: code.value,
merge: false,
+5 -1
View File
@@ -5,7 +5,7 @@ from collections import defaultdict
from flectra import api, fields, models, _
from flectra.exceptions import UserError
from flectra.tools import float_is_zero, OrderedSet
from flectra.tools import float_compare, float_is_zero, OrderedSet
import logging
_logger = logging.getLogger(__name__)
@@ -40,6 +40,10 @@ class StockMove(models.Model):
# If the move is a return, use the original move's price unit.
if self.origin_returned_move_id and self.origin_returned_move_id.sudo().stock_valuation_layer_ids:
layers = self.origin_returned_move_id.sudo().stock_valuation_layer_ids
# dropshipping create additional positive svl to make sure there is no impact on the stock valuation
# We need to remove them from the computation of the price unit.
if self.origin_returned_move_id._is_dropshipped():
layers = layers.filtered(lambda l: float_compare(l.value, 0, precision_rounding=l.product_id.uom_id.rounding) <= 0)
layers |= layers.stock_valuation_layer_ids
quantity = sum(layers.mapped("quantity"))
return layers.currency_id.round(sum(layers.mapped("value")) / quantity) if not float_is_zero(quantity, precision_rounding=layers.uom_id.rounding) else 0
@@ -298,3 +298,29 @@ class TestStockValuation(ValuationReconciliationTestCommon):
}
self._check_results(expected_aml, 4, all_amls_return - all_amls)
def test_dropship_fifo_return(self):
"""Test the return of a dropship order with a product set to FIFO costing
method. The unit price is correctly computed on the return picking svl.
"""
self.env.company.anglo_saxon_accounting = True
self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo'
self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time'
self.product1.product_tmpl_id.invoice_policy = 'order'
self._dropship_product1()
self.assertTrue(8 in self.purchase_order1.picking_ids.move_lines.stock_valuation_layer_ids.mapped('value'))
self.assertTrue(-8 in self.purchase_order1.picking_ids.move_lines.stock_valuation_layer_ids.mapped('value'))
# return what we've done
stock_return_picking_form = Form(self.env['stock.return.picking']
.with_context(active_ids=self.sale_order1.picking_ids.ids, active_id=self.sale_order1.picking_ids.ids[0],
active_model='stock.picking'))
stock_return_picking = stock_return_picking_form.save()
stock_return_picking_action = stock_return_picking.create_returns()
return_pick = self.env['stock.picking'].browse(stock_return_picking_action['res_id'])
return_pick.move_lines[0].move_line_ids[0].qty_done = 1.0
return_pick._action_done()
self.assertTrue(8 in return_pick.move_lines.stock_valuation_layer_ids.mapped('value'))
self.assertTrue(-8 in return_pick.move_lines.stock_valuation_layer_ids.mapped('value'))
@@ -120,9 +120,12 @@ class TestMultiCompanySetup(TestMailCommon, TestRecipients):
)
test_records[0].activity_schedule("test_mail.mail_act_test_todo", user_id=user_admin.id)
test_records[1].activity_schedule("test_mail.mail_act_test_todo", user_id=user_admin.id)
res_all = user_admin.systray_get_activities()
test_activity = next(
a for a in user_admin.systray_get_activities()
if a['model'] == 'mail.test.multi.company.with.activity'
)
self.assertEqual(
res_all[0],
test_activity,
{
"actions": [{"icon": "fa-clock-o", "name": "Summary"}],
"icon": "/base/static/description/icon.png",
@@ -135,9 +138,13 @@ class TestMultiCompanySetup(TestMailCommon, TestRecipients):
"type": "activity",
}
)
res_c2 = user_admin.with_context(allowed_company_ids=[self.company_2.id]).systray_get_activities()
test_activity = next(
a for a in user_admin.with_context(allowed_company_ids=[self.company_2.id]).systray_get_activities()
if a['model'] == 'mail.test.multi.company.with.activity'
)
self.assertEqual(
res_c2[0],
test_activity,
{
"actions": [{"icon": "fa-clock-o", "name": "Summary"}],
"icon": "/base/static/description/icon.png",
@@ -13,7 +13,7 @@ const TableOfContent = publicWidget.Widget.extend({
*/
async start() {
await this._super(...arguments);
this.$scrollingElement = $().getScrollingElement();
this.$scrollingElement = this.$target.closest(".s_table_of_content").closestScrollable();
this.previousPosition = -1;
this._updateTableOfContentNavbarPosition();
extraMenuUpdateCallbacks.push(this._updateTableOfContentNavbarPosition.bind(this));
@@ -134,7 +134,7 @@ publicWidget.registry.websiteForum = publicWidget.Widget.extend({
toolbar.push(['history', ['undo', 'redo']]);
var options = {
height: 200,
height: 350,
minHeight: 80,
toolbar: toolbar,
styleWithSpan: false,
@@ -202,7 +202,10 @@ publicWidget.registry.websiteForum = publicWidget.Widget.extend({
let $title = $form.find('input[name=post_name]');
let $textarea = $form.find('textarea[name=content]');
// It's not really in the textarea that the user write at first
let textareaContent = $form.find('.o_wysiwyg_wrapper .note-editable.panel-body').text().trim();
const fillableTextAreaEl = ev.currentTarget
.querySelector(".o_wysiwyg_wrapper .note-editable.panel-body");
const isTextAreaFilled = fillableTextAreaEl &&
(fillableTextAreaEl.innerText.trim() || fillableTextAreaEl.querySelector("img"));
if ($title.length && $title[0].required) {
if ($title.val()) {
@@ -216,7 +219,7 @@ publicWidget.registry.websiteForum = publicWidget.Widget.extend({
// Because the textarea is hidden, we add the red or green border to its container
if ($textarea[0] && $textarea[0].required) {
let $textareaContainer = $form.find('.o_wysiwyg_wrapper .note-editor.panel.panel-default');
if (!textareaContent.length) {
if (!isTextAreaFilled) {
$textareaContainer.addClass('border border-danger rounded-top');
validForm = false;
} else {