Merge branch 'cor_cr' of https://gitlab.sunarctechnologies.com/prakash.jain/cor-odoo into cor_cr
This commit is contained in:
commit
79a3e34f90
|
@ -419,6 +419,25 @@ class InheritProjectProductEmployeeMap(models.Model):
|
|||
# line.price_unit = 0
|
||||
line.currency_id = False
|
||||
|
||||
def edit_sale_line_employee_record(self):
|
||||
context = dict(self.env.context)
|
||||
context['form_view_initial_mode'] = 'edit'
|
||||
return {
|
||||
'name': ('Edit Resource History'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_type': 'form',
|
||||
'view_mode': 'form',
|
||||
'target': 'new',
|
||||
'res_model': 'project.sale.line.employee.map',
|
||||
'res_id': self.id,
|
||||
'context': context,
|
||||
# 'view_id': view_id
|
||||
}
|
||||
|
||||
def update_record(self):
|
||||
return {
|
||||
'type': 'ir.actions.act_window_close'}
|
||||
|
||||
|
||||
class CustomProjectTags(models.Model):
|
||||
""" Tags of project's tasks """
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
<field name="inherit_id" ref="sale_timesheet.project_project_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@name='options_active']/div" position="after">
|
||||
<div name="creation_div" attrs="{'invisible': [('id', '=', False)]}">
|
||||
<div name="creation_div" attrs="{'invisible': [('id', '=', False)]}"
|
||||
groups="project.group_project_manager">
|
||||
<label for="create_date" class="oe_inline" string="Created On"/>
|
||||
<field name="create_date" readonly="1" class="oe_inline"/>
|
||||
</div>
|
||||
|
@ -17,7 +18,7 @@
|
|||
icon="fa-puzzle-piece" attrs="{'invisible': [('allow_billable', '=', False)]}" invisible="1"/>
|
||||
</xpath>
|
||||
<xpath expr="//page[@name='billing_employee_rate']" position="replace">
|
||||
<page name="billing_employee_rate" string="Invoicing"
|
||||
<page name="billing_employee_rate" string="Invoicing" groups="project.group_project_manager"
|
||||
attrs="{'invisible': [('allow_billable', '=', False)]}">
|
||||
<group>
|
||||
<field name="display_create_order" invisible="1"/>
|
||||
|
@ -61,7 +62,9 @@
|
|||
options="{'no_create': True, 'no_edit': True, 'delete': False}"/>
|
||||
<field name="is_check" invisible="1"/>
|
||||
</group>
|
||||
<button name="%(action_project_resource_wizard)d" string="Add Resource" type="action" groups="project.group_project_manager" class="oe_highlight"/>
|
||||
<button name="%(action_project_resource_wizard)d" string="Add Resource" type="action"
|
||||
attrs="{'invisible': [('pricing_type','=','fixed_rate')]}"
|
||||
groups="project.group_project_manager" class="oe_highlight"/>
|
||||
<field name="sale_line_employee_ids"
|
||||
attrs="{'invisible': ['|', ('bill_type', '!=', 'customer_project'), ('pricing_type', '!=', 'employee_rate')]}">
|
||||
<tree editable="top" create="false">
|
||||
|
@ -97,6 +100,8 @@
|
|||
<field name="consultant_cost"/>
|
||||
<field name="actual_revenue"/>
|
||||
<field name="budgeted_hour_week" invisible="1"/>
|
||||
<button type="object" name="edit_sale_line_employee_record" string="Edit" class="oe_highlight"/>
|
||||
<button name="unlink" type="object" icon="fa-trash-o"/>
|
||||
</tree>
|
||||
</field>
|
||||
<!--<field name="consultant_timesheet_hrs" readonly="1" attrs="{'invisible': [('pricing_type','!=','fixed_rate')]}">-->
|
||||
|
@ -150,15 +155,16 @@
|
|||
</div>-->
|
||||
<xpath expr="//field[@name='user_id']" position="replace">
|
||||
<field name="user_id" string="Project Manager" widget="many2one_avatar_user" required="0"
|
||||
groups="project.group_project_manager"
|
||||
attrs="{'readonly':[('active','=',False)]}" domain="[('share', '=', False)]"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='partner_id']" position="replace">
|
||||
<field name="partner_id" string="Client" required="0"/>
|
||||
<field name="date_start"/>
|
||||
<field name="date"/>
|
||||
<field name="partner_id" string="Client" required="0" groups="project.group_project_manager"/>
|
||||
<field name="date_start" groups="project.group_project_manager"/>
|
||||
<field name="date" groups="project.group_project_manager"/>
|
||||
</xpath>
|
||||
<xpath expr="//page[@name='settings']" position="after">
|
||||
<page string="Consultant Allocation"
|
||||
<page string="Consultant Allocation" groups="project.group_project_manager"
|
||||
attrs="{'invisible':['|',('pricing_type','!=','employee_rate'),('project_type','!=','hours_in_consultant')]}">
|
||||
<field name="project_cons_hrs">
|
||||
<tree editable="top">
|
||||
|
@ -174,8 +180,15 @@
|
|||
</field>
|
||||
</page>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='privacy_visibility']" position="replace">
|
||||
<field name="privacy_visibility" widget="radio" groups="project.group_project_manager"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='allowed_internal_user_ids']" position="replace">
|
||||
<field name="allowed_internal_user_ids" widget="many2many_tags" groups="project.group_project_manager"
|
||||
attrs="{'invisible': [('privacy_visibility', '!=', 'followers')]}"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='privacy_visibility']" position="before">
|
||||
<field name="tag_ids" widget="many2many_tags"/>
|
||||
<field name="tag_ids" widget="many2many_tags" groups="project.group_project_manager"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -259,6 +272,44 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_project_sale_line_employee_map" model="ir.ui.view">
|
||||
<field name="name"> project.sale.line.employee.map.lines</field>
|
||||
<field name="model">project.sale.line.employee.map</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Project Sale Employee Lines">
|
||||
<group>
|
||||
<group>
|
||||
<field name="project_id"/>
|
||||
<field name="sale_line_id"/>
|
||||
<field name="timesheet_product_id"/>
|
||||
<field name="currency_id"/>
|
||||
<field name="budgeted_uom"/>
|
||||
<field name="employee_price"/>
|
||||
<field name="cost"/>
|
||||
<field name="role"/>
|
||||
<field name="start_date"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="employee_id"/>
|
||||
<field name="company_id"/>
|
||||
<field name="price_unit"/>
|
||||
<field name="budgeted_qty"/>
|
||||
<field name="timesheet_hour"/>
|
||||
<field name="budgeted_hour_week"/>
|
||||
<field name="consultant_cost"/>
|
||||
<field name="hour_distribution"/>
|
||||
<field name="distribution_per"/>
|
||||
<field name="end_date"/>
|
||||
</group>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="update_record" type="object" string="Update" class="oe_highlight"/>
|
||||
<button special="cancel" string="Cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Done Task action -->
|
||||
<record id="project_task_server_action_batch_done" model="ir.actions.server">
|
||||
<field name="name">Done</field>
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
'name': 'Month Filter',
|
||||
'version': '1.0.1',
|
||||
|
||||
'author': 'SunArc Technologies',
|
||||
'website': 'www.sunarctechnologies.com',
|
||||
'license': 'LGPL-3',
|
||||
'depends': ['base','web' ,'hr_timesheet'],
|
||||
'data': [
|
||||
'views/templates.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
odoo.define('month_filter.ModeExtension', function (require) {
|
||||
"use strict";
|
||||
const components = {
|
||||
ControlPanelModelExtension: require("web/static/src/js/control_panel/control_panel_model_extension.js"),
|
||||
};
|
||||
const { patch } = require("web.utils");
|
||||
const Domain = require('web.Domain');
|
||||
const pyUtils = require('web.py_utils');
|
||||
|
||||
const { DEFAULT_INTERVAL, DEFAULT_PERIOD,
|
||||
getComparisonOptions, getIntervalOptions, getPeriodOptions,
|
||||
constructDateDomain, rankInterval, yearSelected } = require('month_filter.searchUtils');
|
||||
|
||||
patch(
|
||||
components.ControlPanelModelExtension,
|
||||
"month_filter/static/src/js/control_panel/control_panel_custom_extension.js",
|
||||
{
|
||||
toggleFilterWithOptions(filterId, optionId) {
|
||||
this.referenceMoment = moment();
|
||||
this.optionGenerators = getPeriodOptions(this.referenceMoment);
|
||||
return this._super(filterId, optionId);
|
||||
},
|
||||
_enrichFilterCopy(filter, filterQueryElements) {
|
||||
this.referenceMoment = moment();
|
||||
this.optionGenerators = getPeriodOptions(this.referenceMoment);
|
||||
return this._super(filter, filterQueryElements);
|
||||
},
|
||||
_getDateFilterDomain(filter, filterQueryElements, key = 'domain') {
|
||||
const { fieldName, fieldType } = filter;
|
||||
const selectedOptionIds = filterQueryElements.map(queryElem => queryElem.optionId);
|
||||
|
||||
const dateFilterRange = constructDateDomain(
|
||||
this.referenceMoment, fieldName, fieldType, selectedOptionIds,
|
||||
);
|
||||
return dateFilterRange[key];
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
|
@ -0,0 +1,578 @@
|
|||
odoo.define('month_filter.searchUtils', function (require) {
|
||||
"use strict";
|
||||
|
||||
const { _lt, _t } = require('web.core');
|
||||
const Domain = require('web.Domain');
|
||||
const pyUtils = require('web.py_utils');
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Constants
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// Filter menu parameters
|
||||
const FIELD_OPERATORS = {
|
||||
boolean: [
|
||||
{ symbol: "=", description: _lt("is true"), value: true },
|
||||
{ symbol: "!=", description: _lt("is false"), value: true },
|
||||
],
|
||||
char: [
|
||||
{ symbol: "ilike", description: _lt("contains") },
|
||||
{ symbol: "not ilike", description: _lt("doesn't contain") },
|
||||
{ symbol: "=", description: _lt("is equal to") },
|
||||
{ symbol: "!=", description: _lt("is not equal to") },
|
||||
{ symbol: "!=", description: _lt("is set"), value: false },
|
||||
{ symbol: "=", description: _lt("is not set"), value: false },
|
||||
],
|
||||
date: [
|
||||
{ symbol: "=", description: _lt("is equal to") },
|
||||
{ symbol: "!=", description: _lt("is not equal to") },
|
||||
{ symbol: ">", description: _lt("is after") },
|
||||
{ symbol: "<", description: _lt("is before") },
|
||||
{ symbol: ">=", description: _lt("is after or equal to") },
|
||||
{ symbol: "<=", description: _lt("is before or equal to") },
|
||||
{ symbol: "between", description: _lt("is between") },
|
||||
{ symbol: "!=", description: _lt("is set"), value: false },
|
||||
{ symbol: "=", description: _lt("is not set"), value: false },
|
||||
],
|
||||
datetime: [
|
||||
{ symbol: "between", description: _lt("is between") },
|
||||
{ symbol: "=", description: _lt("is equal to") },
|
||||
{ symbol: "!=", description: _lt("is not equal to") },
|
||||
{ symbol: ">", description: _lt("is after") },
|
||||
{ symbol: "<", description: _lt("is before") },
|
||||
{ symbol: ">=", description: _lt("is after or equal to") },
|
||||
{ symbol: "<=", description: _lt("is before or equal to") },
|
||||
{ symbol: "!=", description: _lt("is set"), value: false },
|
||||
{ symbol: "=", description: _lt("is not set"), value: false },
|
||||
],
|
||||
id: [
|
||||
{ symbol: "=", description: _lt("is") },
|
||||
{ symbol: "<=", description: _lt("less than or equal to")},
|
||||
{ symbol: ">", description: _lt("greater than")},
|
||||
],
|
||||
number: [
|
||||
{ symbol: "=", description: _lt("is equal to") },
|
||||
{ symbol: "!=", description: _lt("is not equal to") },
|
||||
{ symbol: ">", description: _lt("greater than") },
|
||||
{ symbol: "<", description: _lt("less than") },
|
||||
{ symbol: ">=", description: _lt("greater than or equal to") },
|
||||
{ symbol: "<=", description: _lt("less than or equal to") },
|
||||
{ symbol: "!=", description: _lt("is set"), value: false },
|
||||
{ symbol: "=", description: _lt("is not set"), value: false },
|
||||
],
|
||||
selection: [
|
||||
{ symbol: "=", description: _lt("is") },
|
||||
{ symbol: "!=", description: _lt("is not") },
|
||||
{ symbol: "!=", description: _lt("is set"), value: false },
|
||||
{ symbol: "=", description: _lt("is not set"), value: false },
|
||||
],
|
||||
};
|
||||
const FIELD_TYPES = {
|
||||
boolean: 'boolean',
|
||||
char: 'char',
|
||||
date: 'date',
|
||||
datetime: 'datetime',
|
||||
float: 'number',
|
||||
id: 'id',
|
||||
integer: 'number',
|
||||
html: 'char',
|
||||
many2many: 'char',
|
||||
many2one: 'char',
|
||||
monetary: 'number',
|
||||
one2many: 'char',
|
||||
text: 'char',
|
||||
selection: 'selection',
|
||||
};
|
||||
const DEFAULT_PERIOD = 'this_month';
|
||||
const QUARTERS = {
|
||||
1: { description: _lt("Q1"), coveredMonths: [0, 1, 2] },
|
||||
2: { description: _lt("Q2"), coveredMonths: [3, 4, 5] },
|
||||
3: { description: _lt("Q3"), coveredMonths: [6, 7, 8] },
|
||||
4: { description: _lt("Q4"), coveredMonths: [9, 10, 11] },
|
||||
};
|
||||
const MONTH_OPTIONS = {
|
||||
this_month: {
|
||||
id: 'this_month', groupNumber: 1, format: 'MMMM',
|
||||
addParam: {}, granularity: 'month',
|
||||
},
|
||||
last_month: {
|
||||
id: 'last_month', groupNumber: 1, format: 'MMMM',
|
||||
addParam: { months: -1 }, granularity: 'month',
|
||||
},
|
||||
antepenultimate_month: {
|
||||
id: 'antepenultimate_month', groupNumber: 1, format: 'MMMM',
|
||||
addParam: { months: -2 }, granularity: 'month',
|
||||
},
|
||||
antepenultimate_month_3: {
|
||||
id: 'antepenultimate_month_3', groupNumber: 1, format: 'MMMM',
|
||||
addParam: { months: -3 }, granularity: 'month',
|
||||
},
|
||||
antepenultimate_month_4: {
|
||||
id: 'antepenultimate_month_4', groupNumber: 1, format: 'MMMM',
|
||||
addParam: { months: -4 }, granularity: 'month',
|
||||
},
|
||||
antepenultimate_month_5: {
|
||||
id: 'antepenultimate_month_5', groupNumber: 1, format: 'MMMM',
|
||||
addParam: { months: -5 }, granularity: 'month',
|
||||
},
|
||||
antepenultimate_month_6: {
|
||||
id: 'antepenultimate_month_6', groupNumber: 1, format: 'MMMM',
|
||||
addParam: { months: -6 }, granularity: 'month',
|
||||
},
|
||||
antepenultimate_month_7: {
|
||||
id: 'antepenultimate_month_7', groupNumber: 1, format: 'MMMM',
|
||||
addParam: { months: -7 }, granularity: 'month',
|
||||
},
|
||||
antepenultimate_month_8: {
|
||||
id: 'antepenultimate_month_8', groupNumber: 1, format: 'MMMM',
|
||||
addParam: { months: -8 }, granularity: 'month',
|
||||
},
|
||||
antepenultimate_month_9: {
|
||||
id: 'antepenultimate_month_9', groupNumber: 1, format: 'MMMM',
|
||||
addParam: { months: -9 }, granularity: 'month',
|
||||
},
|
||||
antepenultimate_month_10: {
|
||||
id: 'antepenultimate_month_10', groupNumber: 1, format: 'MMMM',
|
||||
addParam: { months: -10 }, granularity: 'month',
|
||||
},
|
||||
antepenultimate_month_11: {
|
||||
id: 'antepenultimate_month_11', groupNumber: 1, format: 'MMMM',
|
||||
addParam: { months: -11 }, granularity: 'month',
|
||||
},
|
||||
};
|
||||
const QUARTER_OPTIONS = {
|
||||
fourth_quarter: {
|
||||
id: 'fourth_quarter', groupNumber: 1, description: QUARTERS[4].description,
|
||||
setParam: { quarter: 4 }, granularity: 'quarter',
|
||||
},
|
||||
third_quarter: {
|
||||
id: 'third_quarter', groupNumber: 1, description: QUARTERS[3].description,
|
||||
setParam: { quarter: 3 }, granularity: 'quarter',
|
||||
},
|
||||
second_quarter: {
|
||||
id: 'second_quarter', groupNumber: 1, description: QUARTERS[2].description,
|
||||
setParam: { quarter: 2 }, granularity: 'quarter',
|
||||
},
|
||||
first_quarter: {
|
||||
id: 'first_quarter', groupNumber: 1, description: QUARTERS[1].description,
|
||||
setParam: { quarter: 1 }, granularity: 'quarter',
|
||||
},
|
||||
};
|
||||
const YEAR_OPTIONS = {
|
||||
this_year: {
|
||||
id: 'this_year', groupNumber: 2, format: 'YYYY',
|
||||
addParam: {}, granularity: 'year',
|
||||
},
|
||||
last_year: {
|
||||
id: 'last_year', groupNumber: 2, format: 'YYYY',
|
||||
addParam: { years: -1 }, granularity: 'year',
|
||||
},
|
||||
antepenultimate_year: {
|
||||
id: 'antepenultimate_year', groupNumber: 2, format: 'YYYY',
|
||||
addParam: { years: -2 }, granularity: 'year',
|
||||
},
|
||||
};
|
||||
const PERIOD_OPTIONS = Object.assign({}, MONTH_OPTIONS, QUARTER_OPTIONS, YEAR_OPTIONS);
|
||||
|
||||
// GroupBy menu parameters
|
||||
const GROUPABLE_TYPES = [
|
||||
'boolean',
|
||||
'char',
|
||||
'date',
|
||||
'datetime',
|
||||
'integer',
|
||||
'many2one',
|
||||
'selection',
|
||||
];
|
||||
const DEFAULT_INTERVAL = 'month';
|
||||
const INTERVAL_OPTIONS = {
|
||||
year: { description: _lt("Year"), id: 'year', groupNumber: 1 },
|
||||
quarter: { description: _lt("Quarter"), id: 'quarter', groupNumber: 1 },
|
||||
month: { description: _lt("Month"), id: 'month', groupNumber: 1 },
|
||||
week: { description: _lt("Week"), id: 'week', groupNumber: 1 },
|
||||
day: { description: _lt("Day"), id: 'day', groupNumber: 1 }
|
||||
};
|
||||
|
||||
// Comparison menu parameters
|
||||
const COMPARISON_OPTIONS = {
|
||||
previous_period: {
|
||||
description: _lt("Previous Period"), id: 'previous_period',
|
||||
},
|
||||
previous_year: {
|
||||
description: _lt("Previous Year"), id: 'previous_year', addParam: { years: -1 },
|
||||
},
|
||||
};
|
||||
const PER_YEAR = {
|
||||
year: 1,
|
||||
quarter: 4,
|
||||
month: 12,
|
||||
};
|
||||
// Search bar
|
||||
const FACET_ICONS = {
|
||||
filter: 'fa fa-filter',
|
||||
groupBy: 'fa fa-bars',
|
||||
favorite: 'fa fa-star',
|
||||
comparison: 'fa fa-adjust',
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Functions
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs the string representation of a domain and its description. The
|
||||
* domain is of the form:
|
||||
* ['|',..., '|', d_1,..., d_n]
|
||||
* where d_i is a time range of the form
|
||||
* ['&', [fieldName, >=, leftBound_i], [fieldName, <=, rightBound_i]]
|
||||
* where leftBound_i and rightBound_i are date or datetime computed accordingly
|
||||
* to the given options and reference moment.
|
||||
* (@see constructDateRange).
|
||||
* @param {moment} referenceMoment
|
||||
* @param {string} fieldName
|
||||
* @param {string} fieldType
|
||||
* @param {string[]} selectedOptionIds
|
||||
* @param {string} [comparisonOptionId]
|
||||
* @returns {{ domain: string, description: string }}
|
||||
*/
|
||||
function constructDateDomain(
|
||||
referenceMoment,
|
||||
fieldName,
|
||||
fieldType,
|
||||
selectedOptionIds,
|
||||
comparisonOptionId
|
||||
) {
|
||||
let addParam;
|
||||
let selectedOptions;
|
||||
if (comparisonOptionId) {
|
||||
[addParam, selectedOptions] = getComparisonParams(
|
||||
referenceMoment,
|
||||
selectedOptionIds,
|
||||
comparisonOptionId);
|
||||
} else {
|
||||
selectedOptions = getSelectedOptions(referenceMoment, selectedOptionIds);
|
||||
}
|
||||
|
||||
const yearOptions = selectedOptions.year;
|
||||
const otherOptions = [
|
||||
...(selectedOptions.quarter || []),
|
||||
...(selectedOptions.month || [])
|
||||
];
|
||||
|
||||
sortPeriodOptions(yearOptions);
|
||||
sortPeriodOptions(otherOptions);
|
||||
|
||||
const ranges = [];
|
||||
for (const yearOption of yearOptions) {
|
||||
const constructRangeParams = {
|
||||
referenceMoment,
|
||||
fieldName,
|
||||
fieldType,
|
||||
addParam,
|
||||
};
|
||||
if (otherOptions.length) {
|
||||
for (const option of otherOptions) {
|
||||
const setParam = Object.assign({},
|
||||
yearOption.setParam,
|
||||
option ? option.setParam : {}
|
||||
);
|
||||
const { granularity } = option;
|
||||
const range = constructDateRange(Object.assign(
|
||||
{ granularity, setParam },
|
||||
constructRangeParams
|
||||
));
|
||||
ranges.push(range);
|
||||
}
|
||||
} else {
|
||||
const { granularity, setParam } = yearOption;
|
||||
const range = constructDateRange(Object.assign(
|
||||
{ granularity, setParam },
|
||||
constructRangeParams
|
||||
));
|
||||
ranges.push(range);
|
||||
}
|
||||
}
|
||||
|
||||
const domain = pyUtils.assembleDomains(ranges.map(range => range.domain), 'OR');
|
||||
const description = ranges.map(range => range.description).join("/");
|
||||
|
||||
return { domain, description };
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the string representation of a domain and its description. The
|
||||
* domain is a time range of the form:
|
||||
* ['&', [fieldName, >=, leftBound],[fieldName, <=, rightBound]]
|
||||
* where leftBound and rightBound are some date or datetime determined by setParam,
|
||||
* addParam, granularity and the reference moment.
|
||||
* @param {Object} params
|
||||
* @param {moment} params.referenceMoment
|
||||
* @param {string} params.fieldName
|
||||
* @param {string} params.fieldType
|
||||
* @param {string} params.granularity
|
||||
* @param {Object} params.setParam
|
||||
* @param {Object} [params.addParam]
|
||||
* @returns {{ domain: string, description: string }}
|
||||
*/
|
||||
function constructDateRange({
|
||||
referenceMoment,
|
||||
fieldName,
|
||||
fieldType,
|
||||
granularity,
|
||||
setParam,
|
||||
addParam,
|
||||
}) {
|
||||
const date = referenceMoment.clone().set(setParam).add(addParam || {});
|
||||
|
||||
// compute domain
|
||||
let leftBound = date.clone().locale('en').startOf(granularity);
|
||||
let rightBound = date.clone().locale('en').endOf(granularity);
|
||||
if (fieldType === 'date') {
|
||||
leftBound = leftBound.format('YYYY-MM-DD');
|
||||
rightBound = rightBound.format('YYYY-MM-DD');
|
||||
} else {
|
||||
leftBound = leftBound.utc().format('YYYY-MM-DD HH:mm:ss');
|
||||
rightBound = rightBound.utc().format('YYYY-MM-DD HH:mm:ss');
|
||||
}
|
||||
const domain = Domain.prototype.arrayToString([
|
||||
'&',
|
||||
[fieldName, '>=', leftBound],
|
||||
[fieldName, '<=', rightBound]
|
||||
]);
|
||||
|
||||
// compute description
|
||||
const descriptions = [date.format("YYYY")];
|
||||
const method = _t.database.parameters.direction === "rtl" ? "push" : "unshift";
|
||||
if (granularity === "month") {
|
||||
descriptions[method](date.format("MMMM"));
|
||||
} else if (granularity === "quarter") {
|
||||
descriptions[method](QUARTERS[date.quarter()].description);
|
||||
}
|
||||
const description = descriptions.join(" ");
|
||||
|
||||
return { domain, description, };
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a version of the options in COMPARISON_OPTIONS with translated descriptions.
|
||||
* @see getOptionsWithDescriptions
|
||||
*/
|
||||
function getComparisonOptions() {
|
||||
return getOptionsWithDescriptions(COMPARISON_OPTIONS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the params addParam and selectedOptions necessary for the computation
|
||||
* of a comparison domain.
|
||||
* @param {moment} referenceMoment
|
||||
* @param {string{}} selectedOptionIds
|
||||
* @param {string} comparisonOptionId
|
||||
* @returns {Object[]}
|
||||
*/
|
||||
function getComparisonParams(referenceMoment, selectedOptionIds, comparisonOptionId) {
|
||||
const comparisonOption = COMPARISON_OPTIONS[comparisonOptionId];
|
||||
const selectedOptions = getSelectedOptions(referenceMoment, selectedOptionIds);
|
||||
let addParam = comparisonOption.addParam;
|
||||
if (addParam) {
|
||||
return [addParam, selectedOptions];
|
||||
}
|
||||
addParam = {};
|
||||
|
||||
let globalGranularity = 'year';
|
||||
if (selectedOptions.month) {
|
||||
globalGranularity = 'month';
|
||||
} else if (selectedOptions.quarter) {
|
||||
globalGranularity = 'quarter';
|
||||
}
|
||||
const granularityFactor = PER_YEAR[globalGranularity];
|
||||
const years = selectedOptions.year.map(o => o.setParam.year);
|
||||
const yearMin = Math.min(...years);
|
||||
const yearMax = Math.max(...years);
|
||||
|
||||
let optionMin = 0;
|
||||
let optionMax = 0;
|
||||
if (selectedOptions.quarter) {
|
||||
const quarters = selectedOptions.quarter.map(o => o.setParam.quarter);
|
||||
if (globalGranularity === 'month') {
|
||||
delete selectedOptions.quarter;
|
||||
for (const quarter of quarters) {
|
||||
for (const month of QUARTERS[quarter].coveredMonths) {
|
||||
const monthOption = selectedOptions.month.find(
|
||||
o => o.setParam.month === month
|
||||
);
|
||||
if (!monthOption) {
|
||||
selectedOptions.month.push({
|
||||
setParam: { month, }, granularity: 'month',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
optionMin = Math.min(...quarters);
|
||||
optionMax = Math.max(...quarters);
|
||||
}
|
||||
}
|
||||
if (selectedOptions.month) {
|
||||
const months = selectedOptions.month.map(o => o.setParam.month);
|
||||
optionMin = Math.min(...months);
|
||||
optionMax = Math.max(...months);
|
||||
}
|
||||
|
||||
addParam[globalGranularity] = -1 +
|
||||
granularityFactor * (yearMin - yearMax) +
|
||||
optionMin - optionMax;
|
||||
|
||||
return [addParam, selectedOptions];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a version of the options in INTERVAL_OPTIONS with translated descriptions.
|
||||
* @see getOptionsWithDescriptions
|
||||
*/
|
||||
function getIntervalOptions() {
|
||||
return getOptionsWithDescriptions(INTERVAL_OPTIONS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a version of the options in PERIOD_OPTIONS with translated descriptions
|
||||
* and a key defautlYearId used in the control panel model when toggling a period option.
|
||||
* @param {moment} referenceMoment
|
||||
* @returns {Object[]}
|
||||
*/
|
||||
function getPeriodOptions(referenceMoment) {
|
||||
const options = [];
|
||||
for (const option of Object.values(PERIOD_OPTIONS)) {
|
||||
const { id, groupNumber, description, } = option;
|
||||
const res = { id, groupNumber, };
|
||||
const date = referenceMoment.clone().set(option.setParam).add(option.addParam);
|
||||
if (description) {
|
||||
res.description = description.toString();
|
||||
} else {
|
||||
res.description = date.format(option.format.toString());
|
||||
}
|
||||
res.setParam = getSetParam(option, referenceMoment);
|
||||
res.defaultYear = date.year();
|
||||
options.push(res);
|
||||
}
|
||||
for (const option of options) {
|
||||
const yearOption = options.find(
|
||||
o => o.setParam && o.setParam.year === option.defaultYear
|
||||
);
|
||||
option.defaultYearId = yearOption.id;
|
||||
delete option.defaultYear;
|
||||
delete option.setParam;
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a version of the options in OPTIONS with translated descriptions (if any).
|
||||
* @param {Object{}} OPTIONS
|
||||
* @returns {Object[]}
|
||||
*/
|
||||
function getOptionsWithDescriptions(OPTIONS) {
|
||||
const options = [];
|
||||
for (const option of Object.values(OPTIONS)) {
|
||||
const { id, groupNumber, description, } = option;
|
||||
const res = { id, };
|
||||
if (description) {
|
||||
res.description = description.toString();
|
||||
}
|
||||
if (groupNumber) {
|
||||
res.groupNumber = groupNumber;
|
||||
}
|
||||
options.push(res);
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a version of the period options whose ids are in selectedOptionIds
|
||||
* partitioned by granularity.
|
||||
* @param {moment} referenceMoment
|
||||
* @param {string[]} selectedOptionIds
|
||||
* @param {Object}
|
||||
*/
|
||||
function getSelectedOptions(referenceMoment, selectedOptionIds) {
|
||||
const selectedOptions = { year: [] };
|
||||
for (const optionId of selectedOptionIds) {
|
||||
const option = PERIOD_OPTIONS[optionId];
|
||||
const setParam = getSetParam(option, referenceMoment);
|
||||
const granularity = option.granularity;
|
||||
if (!selectedOptions[granularity]) {
|
||||
selectedOptions[granularity] = [];
|
||||
}
|
||||
selectedOptions[granularity].push({ granularity, setParam });
|
||||
}
|
||||
return selectedOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the setParam object associated with the given periodOption and
|
||||
* referenceMoment.
|
||||
* @param {Object} periodOption
|
||||
* @param {moment} referenceMoment
|
||||
* @returns {Object}
|
||||
*/
|
||||
function getSetParam(periodOption, referenceMoment) {
|
||||
if (periodOption.setParam) {
|
||||
return periodOption.setParam;
|
||||
}
|
||||
const date = referenceMoment.clone().add(periodOption.addParam);
|
||||
const setParam = {};
|
||||
setParam[periodOption.granularity] = date[periodOption.granularity]();
|
||||
return setParam;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} intervalOptionId
|
||||
* @returns {number} index
|
||||
*/
|
||||
function rankInterval(intervalOptionId) {
|
||||
return Object.keys(INTERVAL_OPTIONS).indexOf(intervalOptionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts in place an array of 'period' options.
|
||||
* @param {Object[]} options supposed to be of the form:
|
||||
* { granularity, setParam, }
|
||||
*/
|
||||
function sortPeriodOptions(options) {
|
||||
options.sort((o1, o2) => {
|
||||
const granularity1 = o1.granularity;
|
||||
const granularity2 = o2.granularity;
|
||||
if (granularity1 === granularity2) {
|
||||
return o1.setParam[granularity1] - o2.setParam[granularity1];
|
||||
}
|
||||
return granularity1 < granularity2 ? -1 : 1;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a year id is among the given array of period option ids.
|
||||
* @param {string[]} selectedOptionIds
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function yearSelected(selectedOptionIds) {
|
||||
return selectedOptionIds.some(optionId => !!YEAR_OPTIONS[optionId]);
|
||||
}
|
||||
|
||||
return {
|
||||
COMPARISON_OPTIONS,
|
||||
DEFAULT_INTERVAL,
|
||||
DEFAULT_PERIOD,
|
||||
FACET_ICONS,
|
||||
FIELD_OPERATORS,
|
||||
FIELD_TYPES,
|
||||
GROUPABLE_TYPES,
|
||||
INTERVAL_OPTIONS,
|
||||
PERIOD_OPTIONS,
|
||||
|
||||
constructDateDomain,
|
||||
getComparisonOptions,
|
||||
getIntervalOptions,
|
||||
getPeriodOptions,
|
||||
rankInterval,
|
||||
yearSelected,
|
||||
};
|
||||
});
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<template id="filter_extend_assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<script type="text/javascript" src="/month_filter/static/src/js/control_panel/custom_search_utils.js"/>
|
||||
<script type="text/javascript" src="/month_filter/static/src/js/control_panel/control_panel_custom_extension.js"/>
|
||||
</xpath>
|
||||
</template>
|
||||
</odoo>
|
|
@ -9,15 +9,47 @@ class CustomProject(models.Model):
|
|||
|
||||
revenue_amount_lines = fields.One2many('project.revenue.lines' , 'project_id')
|
||||
|
||||
|
||||
class ProjectRevenueLines(models.Model):
|
||||
_name = 'project.revenue.lines'
|
||||
|
||||
project_id = fields.Many2one('project.project')
|
||||
start_date = fields.Date(required=True)
|
||||
end_date = fields.Date(required=True)
|
||||
# start_date = fields.Date(required=True)
|
||||
# end_date = fields.Date(required=True)
|
||||
date = fields.Date(required=True)
|
||||
fixed_amount = fields.Float()
|
||||
|
||||
|
||||
def edit_revenue_history_record(self):
|
||||
context = dict(self.env.context)
|
||||
context['form_view_initial_mode'] = 'edit'
|
||||
return {
|
||||
'name': ('Edit Revenue History'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_type': 'form',
|
||||
'view_mode': 'form',
|
||||
'target': 'new',
|
||||
'res_model': 'project.revenue.lines',
|
||||
'res_id': self.id,
|
||||
'context': context,
|
||||
# 'view_id': view_id
|
||||
}
|
||||
|
||||
"""@api.onchange('start_date')
|
||||
def _onchange_start_date(self):
|
||||
if self.project_id:
|
||||
records = self.env['project.revenue.lines'].sudo().search([('project_id', '=', self.project_id.id)])
|
||||
if self.start_date:
|
||||
if self.start_date.day != 1:
|
||||
raise AccessError('Please select first date of month')
|
||||
else:
|
||||
pass
|
||||
for line in records:
|
||||
if self.start_date >= line.start_date and self.start_date <= line.end_date:
|
||||
raise AccessError('Date already exist')"""
|
||||
|
||||
def update_record(self):
|
||||
return {
|
||||
'type': 'ir.actions.act_window_close'}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_project_revenue_lines,access.project.revenue.lines,model_project_revenue_lines,,1,1,1,0
|
||||
access_project_revenue_wizard,access.project.revenue.wizard,model_project_revenue_wizard,,1,1,1,0
|
||||
access_project_revenue_lines,access.project.revenue.lines,model_project_revenue_lines,project.group_project_manager,1,1,1,1
|
||||
access_project_revenue_wizard,access.project.revenue.wizard,model_project_revenue_wizard,project.group_project_manager,1,1,1,1
|
||||
|
|
|
|
@ -10,9 +10,14 @@
|
|||
<field name="revenue_amount_lines" context="{'project_id' : active_id}" readonly="1">
|
||||
<tree editable="bottom">
|
||||
<field name="project_id" invisible="1"/>
|
||||
<field name="start_date"/>
|
||||
<field name="end_date"/>
|
||||
<!--<field name="start_date"/>
|
||||
<field name="end_date"/>-->
|
||||
<field name="date"/>
|
||||
<field name="fixed_amount"/>
|
||||
<button type="object" name="edit_revenue_history_record" string="Edit" class="oe_highlight"/>
|
||||
<button name="unlink"
|
||||
type="object"
|
||||
icon="fa-trash-o"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
|
@ -20,4 +25,26 @@
|
|||
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_project_revenue_history_lines" model="ir.ui.view">
|
||||
<field name="name"> project.edit.project.revenue.lines</field>
|
||||
<field name="model">project.revenue.lines</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Project Revenue History">
|
||||
<group>
|
||||
<group>
|
||||
<field name="project_id" readonly="1"/>
|
||||
<!--<field name="start_date"/>
|
||||
<field name="end_date"/>-->
|
||||
<field name="date"/>
|
||||
<field name="fixed_amount"/>
|
||||
</group>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="update_record" type="object" string="Update" class="oe_highlight"/>
|
||||
<button special="cancel" string="Cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
|
@ -8,9 +8,10 @@ class CustomProjectWizard(models.TransientModel):
|
|||
_name = 'project.revenue.wizard'
|
||||
|
||||
project_id = fields.Many2one('project.project')
|
||||
start_date = fields.Date(required=True)
|
||||
#start_date = fields.Date(required=True)
|
||||
#end_date = fields.Datet(compute='_compute_end_date', store=True)
|
||||
end_date = fields.Date()
|
||||
#end_date = fields.Date()
|
||||
date = fields.Date(required=True)
|
||||
fixed_amount = fields.Float()
|
||||
|
||||
# @api.depends('start_date')
|
||||
|
@ -20,22 +21,23 @@ class CustomProjectWizard(models.TransientModel):
|
|||
# rec.end_date = rec.start_date + relativedelta.relativedelta(months=1) - relativedelta.relativedelta(
|
||||
# days=1)
|
||||
|
||||
@api.depends('start_date')
|
||||
"""@api.depends('start_date')
|
||||
def _compute_end_date(self):
|
||||
if self.start_date:
|
||||
self.end_date = self.start_date + relativedelta.relativedelta(months=1) - relativedelta.relativedelta(days=1)
|
||||
self.end_date = self.start_date + relativedelta.relativedelta(months=1) - relativedelta.relativedelta(days=1)"""
|
||||
|
||||
def action_set_revenue_lines(self):
|
||||
values = {
|
||||
'project_id':self.project_id.id,
|
||||
'start_date':self.start_date,
|
||||
'end_date':self.end_date,
|
||||
# 'start_date':self.start_date,
|
||||
# 'end_date':self.end_date,
|
||||
'date':self.date,
|
||||
'fixed_amount':self.fixed_amount
|
||||
}
|
||||
res = self.env['project.revenue.lines'].create(values)
|
||||
return res
|
||||
|
||||
@api.onchange('start_date')
|
||||
"""@api.onchange('start_date')
|
||||
def _onchange_start_date(self):
|
||||
active_id = self._context.get('active_ids', [])
|
||||
project_object = self.env['project.project'].search([('id', '=', active_id[0])])
|
||||
|
@ -47,4 +49,4 @@ class CustomProjectWizard(models.TransientModel):
|
|||
self.project_id = project_object.id
|
||||
for line in records:
|
||||
if self.start_date >= line.start_date and self.start_date <= line.end_date:
|
||||
raise AccessError('Date already exist')
|
||||
raise AccessError('Date already exist')"""
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
<odoo>
|
||||
<record id="view_edit_project_wizard_revenue" model="ir.ui.view">
|
||||
<field name="name"> project.edit.project.inherit,wizard</field>
|
||||
<field name="name"> project.edit.project.inherit.wizard</field>
|
||||
<field name="model">project.revenue.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Project Revenue Wizard">
|
||||
<group>
|
||||
<group>
|
||||
<field name="project_id" readonly="1"/>
|
||||
<field name="start_date"/>
|
||||
<field name="end_date"/>
|
||||
<!--<field name="start_date"/>
|
||||
<field name="end_date"/>-->
|
||||
<field name="date"/>
|
||||
<field name="fixed_amount"/>
|
||||
|
||||
</group>
|
||||
</group>
|
||||
<footer>
|
||||
<button string="OK" type="object" name="action_set_revenue_lines" class="btn-primary"/>
|
||||
<button string="Cancel" class="btn-default" special="cancel"/>
|
||||
</footer>
|
||||
<button string="OK" type="object" name="action_set_revenue_lines" class="btn-primary"/>
|
||||
<button string="Cancel" class="btn-default" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -58,13 +58,13 @@
|
|||
</button>
|
||||
</div>
|
||||
<xpath expr="//field[@name='allowed_internal_user_ids']" position="after">
|
||||
<field name="is_sub_project" invisible="0"/>
|
||||
<field name="is_sub_project" invisible="0" groups="project.group_project_manager"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='allowed_internal_user_ids']" position="after">
|
||||
<field name="parent_project" attrs="{'invisible': [('is_sub_project', '=', False)]}"/>
|
||||
<field name="parent_project" attrs="{'invisible': [('is_sub_project', '=', False)]}" groups="project.group_project_manager"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='allowed_internal_user_ids']" position="after">
|
||||
<field name="sub_project" widget="many2many_tags"
|
||||
<field name="sub_project" widget="many2many_tags" groups="project.group_project_manager"
|
||||
attrs="{'invisible': [('is_sub_project', '=', True)]}"
|
||||
options="{'no_open': True, 'no_create': True, 'no_create_edit': True}"/>
|
||||
</xpath>
|
||||
|
|
|
@ -5,7 +5,7 @@ class ResConfigSettingsTimesheet(models.TransientModel):
|
|||
|
||||
timesheet_edit_create_limit = fields.Integer('No. of days',default=0, config_parameter='timesheet_block.timesheet_edit_create_limit')
|
||||
|
||||
timesheet_edit_create_months = fields.Integer('No. of months',default=1, config_parameter='timesheet_block.timesheet_edit_create_months')
|
||||
# timesheet_edit_create_months = fields.Integer('No. of months',default=1, config_parameter='timesheet_block.timesheet_edit_create_months')
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ class TimehseetBlock(models.Model):
|
|||
def create(self, values):
|
||||
current_date = datetime.today().date()
|
||||
entry_date = datetime.strptime(values['date'], "%Y-%m-%d").date()
|
||||
# values['date'] = datetime.strptime(values['date'], "%Y-%m-%d %H:%M:%S")
|
||||
months_diff = current_date.month - entry_date.month
|
||||
employee_object = self.env['hr.employee'].sudo().search([('user_id', '=', self.env.uid)])
|
||||
project_manager_group = self.env.ref('hr_timesheet.group_timesheet_manager')
|
||||
|
@ -38,44 +39,75 @@ class TimehseetBlock(models.Model):
|
|||
config_days_limit = float(config.get_param('timesheet_block.timesheet_edit_create_limit'))
|
||||
if entry_date <= current_date:
|
||||
if self.env.uid not in project_manager_group.users.ids:
|
||||
if months_diff == 0:
|
||||
res = super(TimehseetBlock, self).create(values)
|
||||
elif months_diff == 1:
|
||||
if employee_object.allow_to_create == 'always' and current_date.day <= config_days_limit:
|
||||
if employee_object.allow_to_create == False:
|
||||
if months_diff == 0:
|
||||
res = super(TimehseetBlock, self).create(values)
|
||||
return res
|
||||
else:
|
||||
raise AccessError('You can not create your backdate entry please connect to Hr/Department Head')
|
||||
raise AccessError('You can not create your backdate entry')
|
||||
elif employee_object.allow_to_create == 'always':
|
||||
res = super(TimehseetBlock, self).create(values)
|
||||
return res
|
||||
else:
|
||||
raise AccessError('You can not create your backdate entry please connect to Hr/Department Head')
|
||||
if months_diff == 0:
|
||||
res = super(TimehseetBlock, self).create(values)
|
||||
return res
|
||||
if months_diff == 1:
|
||||
if current_date.day <= config_days_limit:
|
||||
res = super(TimehseetBlock, self).create(values)
|
||||
return res
|
||||
else:
|
||||
raise AccessError('You can not create your backdate entry ')
|
||||
else:
|
||||
raise AccessError('You can not create your backdate entry ')
|
||||
else:
|
||||
res = super(TimehseetBlock, self).create(values)
|
||||
return res
|
||||
else:
|
||||
raise AccessError('You can not create future entry')
|
||||
return res
|
||||
|
||||
|
||||
|
||||
def write(self, values):
|
||||
current_date = datetime.today().date()
|
||||
if 'date' in values:
|
||||
entry_date = datetime.strptime(values['date'], "%Y-%m-%d").date()
|
||||
# values['date'] = datetime.strptime(values['date'], "%Y-%m-%d %H:%M:%S")
|
||||
else:
|
||||
res_date = str(self.date).split('.', 1)[0]
|
||||
entry_date = datetime.strptime(str(res_date), '%Y-%m-%d %H:%M:%S').date()
|
||||
entry_date = datetime.strptime(str(res_date), '%Y-%m-%d').date()
|
||||
months_diff = current_date.month - entry_date.month
|
||||
employee_object = self.env['hr.employee'].sudo().search([('user_id', '=', self.env.uid)])
|
||||
project_manager_group = self.env.ref('hr_timesheet.group_timesheet_manager')
|
||||
config = self.env['ir.config_parameter'].sudo()
|
||||
config_days_limit = float(config.get_param('timesheet_block.timesheet_edit_create_limit'))
|
||||
if self.env.uid not in project_manager_group.users.ids:
|
||||
if months_diff == 0:
|
||||
res = super(TimehseetBlock, self).write(values)
|
||||
elif months_diff == 1:
|
||||
if employee_object.allow_to_edit == 'always' and current_date.day <= config_days_limit:
|
||||
if entry_date <= current_date:
|
||||
if self.env.uid not in project_manager_group.users.ids:
|
||||
if employee_object.allow_to_edit == False:
|
||||
if months_diff == 0:
|
||||
res = super(TimehseetBlock, self).write(values)
|
||||
return res
|
||||
else:
|
||||
raise AccessError('You can not edit your backdate entry ')
|
||||
elif employee_object.allow_to_edit == 'always':
|
||||
res = super(TimehseetBlock, self).write(values)
|
||||
return res
|
||||
else:
|
||||
raise AccessError('You can not edit your backdate entry please connect to Hr/Department Head')
|
||||
if months_diff == 0:
|
||||
res = super(TimehseetBlock, self).write(values)
|
||||
return res
|
||||
if months_diff == 1:
|
||||
if current_date.day <= config_days_limit:
|
||||
res = super(TimehseetBlock, self).write(values)
|
||||
return res
|
||||
else:
|
||||
raise AccessError(
|
||||
'You can not edit your backdate entry ')
|
||||
else:
|
||||
raise AccessError('You can not edit your backdate entry ')
|
||||
else:
|
||||
raise AccessError('You can not edit your backdate entry please connect to Hr/Department Head')
|
||||
res = super(TimehseetBlock, self).write(values)
|
||||
return res
|
||||
else:
|
||||
res = super(TimehseetBlock, self).write(values)
|
||||
return res
|
||||
raise AccessError('You can not create future entry')
|
||||
|
||||
|
|
|
@ -17,12 +17,12 @@
|
|||
<field name="timesheet_edit_create_limit"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="timesheet_edit_create_months"/>
|
||||
<div >
|
||||
<field name="timesheet_edit_create_months"/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="o_setting_right_pane">-->
|
||||
<!-- <label for="timesheet_edit_create_months"/>-->
|
||||
<!-- <div >-->
|
||||
<!-- <field name="timesheet_edit_create_months"/>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue