Merge branch 'copy_master' into 'master'
Copy master See merge request prakash.jain/cor-odoo!226
|
@ -51,6 +51,8 @@ class Project(models.Model):
|
|||
consultant_cost = fields.Float("Actual Cost", compute='_compute_calc')
|
||||
actual_revenue = fields.Float("Actual Revenue", compute='_compute_calc')
|
||||
other_expenses = fields.Float(string='Other Expenses', related='expenses_amt')
|
||||
other_emp_hour = fields.Float("Other Employee Hour", compute='_compute_other_employee_cost')
|
||||
other_emp_cost = fields.Float("Other Employee Cost", compute='_compute_other_employee_cost')
|
||||
total_expenses = fields.Float(string='Total Expenses', digits=(16, 2), compute='_compute_calc', store=True)
|
||||
hourly_rate = fields.Float("Hourly Rate", default=0.0)
|
||||
hourly_rate2 = fields.Float("Hourly Ratee")
|
||||
|
@ -72,6 +74,7 @@ class Project(models.Model):
|
|||
project_cons_hrs = fields.One2many('project.consultant.hrs', 'project_id', 'Consultant Allocation', copy=False)
|
||||
comment = fields.Text(string='Comment')
|
||||
tag_ids = fields.Many2many('custom.project.tags', string='Tags')
|
||||
is_check = fields.Boolean()
|
||||
|
||||
@api.onchange('allowed_internal_user_ids')
|
||||
def onchange_add_allowed_internal_users(self):
|
||||
|
@ -93,7 +96,7 @@ class Project(models.Model):
|
|||
if self._origin.id:
|
||||
if self.pricing_type == 'employee_rate':
|
||||
self.sale_line_employee_ids.create({'project_id': self._origin.id,
|
||||
'employee_id': employee})
|
||||
'employee_id': employee})
|
||||
|
||||
def _onchange_calculate_timesheet_hours(self):
|
||||
self.consultant_timesheet_hrs = [(6, 0, False)]
|
||||
|
@ -109,7 +112,28 @@ class Project(models.Model):
|
|||
'employee_id': rec[1],
|
||||
'timesheet_hour': rec[2]})
|
||||
|
||||
@api.depends('cost', 'expenses_amt', 'budgeted_revenue')
|
||||
def _compute_other_employee_cost(self):
|
||||
for val in self:
|
||||
#######Code for order line consultant
|
||||
list1 = []
|
||||
if val.sale_line_employee_ids:
|
||||
for record1 in val.sale_line_employee_ids:
|
||||
list1.append(record1.employee_id.id)
|
||||
if val._origin.id:
|
||||
self._cr.execute('''SELECT project_id, employee_id, SUM(unit_amount), SUM(amount) FROM account_analytic_line
|
||||
where project_id = %(project_id)s
|
||||
GROUP BY project_id, employee_id''', {'project_id': val._origin.id})
|
||||
res = self._cr.fetchall()
|
||||
hour = 0.0
|
||||
cost = 0.0
|
||||
for record2 in res:
|
||||
if record2[1] not in list1:
|
||||
hour = hour + record2[2]
|
||||
cost = cost + abs(record2[3])
|
||||
val.other_emp_hour = hour
|
||||
val.other_emp_cost = cost
|
||||
|
||||
@api.depends('cost', 'expenses_amt', 'budgeted_revenue', 'is_check')
|
||||
def _compute_calc(self):
|
||||
for record in self:
|
||||
consultant_cost = 0.0
|
||||
|
@ -132,15 +156,16 @@ class Project(models.Model):
|
|||
record.actual_revenue = record.hourly_rate * timesheet_hour
|
||||
record.budgeted_hours = hour
|
||||
record.timesheet_hour = timesheet_hour
|
||||
total_exp = record.consultant_cost + record.expenses_amt
|
||||
#total_exp = record.consultant_cost + record.expenses_amt
|
||||
total_exp = record.consultant_cost + record.other_emp_cost + record.expenses_amt
|
||||
record.total_expenses = total_exp
|
||||
#record.profit_amt = record.budgeted_revenue - total_exp
|
||||
# record.profit_amt = record.budgeted_revenue - total_exp
|
||||
# if record.profit_amt > 0 and record.budgeted_revenue > 0:
|
||||
# record.profit_per = (record.profit_amt / record.budgeted_revenue) * 100
|
||||
|
||||
##### CR Changes
|
||||
record.profit_amt = record.actual_revenue - record.consultant_cost
|
||||
if record.profit_amt > 0:
|
||||
record.profit_amt = record.actual_revenue - record.total_expenses
|
||||
if record.actual_revenue > 0.0:
|
||||
record.profit_per = (record.profit_amt / record.actual_revenue) * 100
|
||||
########################
|
||||
if record.project_type == 'hours_in_consultant' and record.budgeted_hours > 0.0:
|
||||
|
@ -216,6 +241,7 @@ class Project(models.Model):
|
|||
'default_res_model': 'project.consultant.hrs.report'}
|
||||
return action
|
||||
|
||||
|
||||
class ProjectConsultantTimesheetHrs(models.Model):
|
||||
_name = 'consultant.timesheet.hrs'
|
||||
_description = 'Project Consultant Timesheet Hrs'
|
||||
|
@ -354,4 +380,3 @@ class InheritProjectTask(models.Model):
|
|||
for stage in self:
|
||||
stage.write({'stage_id': stage_id.id,
|
||||
'active': False})
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
<field name="sale_line_id" string="Default Sales Order Item"
|
||||
invisible="1"
|
||||
options="{'no_create': True, 'no_edit': True, 'delete': False}"/>
|
||||
<field name="is_check" invisible="1"/>
|
||||
</group>
|
||||
<field name="sale_line_employee_ids"
|
||||
attrs="{'invisible': ['|', ('bill_type', '!=', 'customer_project'), ('pricing_type', '!=', 'employee_rate')]}">
|
||||
|
@ -110,6 +111,7 @@
|
|||
<!--<field name="cost"/>-->
|
||||
<field name="actual_revenue"/>
|
||||
<field name="consultant_cost"/>
|
||||
<field name="other_emp_cost"/>
|
||||
<field name="other_expenses" readonly="1"/>
|
||||
<field name="total_expenses"/>
|
||||
<field name="profit_amt"/>
|
||||
|
@ -121,6 +123,7 @@
|
|||
<field name="budgeted_hours2" attrs="{'invisible': [('project_type','!=','hours_no_limit')],
|
||||
'required': [('project_type','=','hours_no_limit')]}"/>
|
||||
<field name="timesheet_hour"/>
|
||||
<field name="other_emp_hour"/>
|
||||
<field name="hourly_rate" attrs="{'readonly': [('project_type','!=','hours_no_limit')]}"/>
|
||||
<field name="budgeted_hour_week" invisible="1"/>
|
||||
</group>
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
'report/project_budget_amt_analysis_views.xml',
|
||||
'report/project_timeline_report_views.xml',
|
||||
'report/project_timesheet_report_views.xml',
|
||||
'report/project_revenue_custom_report_views.xml',
|
||||
'report/project_revenue_custom_report2_views.xml',
|
||||
'report/project_consultant_custom_report_views.xml',
|
||||
#'report/cor_project_report_views.xml',
|
||||
],
|
||||
'qweb': [
|
||||
"static/src/xml/base.xml",
|
||||
|
|
|
@ -5,3 +5,7 @@ from . import project_budget_hrs_analysis
|
|||
from . import project_budget_amt_analysis
|
||||
from . import project_timeline_report
|
||||
from . import project_timesheet_report
|
||||
from . import project_revenue_custom_report
|
||||
from . import project_revenue_custom_report2
|
||||
from . import project_consultant_custom_report
|
||||
#from . import cor_project_report
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields, models, tools, api
|
||||
|
||||
|
||||
class CorProjectReport(models.Model):
|
||||
_name = "cor.project.report"
|
||||
_description = "COR Project Report"
|
||||
# _order = 'project_id'
|
||||
_auto = False
|
||||
|
||||
project_id = fields.Many2one('project.project', string='Project', readonly=True)
|
||||
employee_id = fields.Many2one('hr.employee', string='Consultant', readonly=True)
|
||||
#hours_type = fields.Char(string="Hours Type", readonly=True)
|
||||
price_unit = fields.Float("Hourly Rate")
|
||||
budgeted_qty = fields.Float(string='Budgeted Hours', digits=(16, 2))
|
||||
cost = fields.Float("Budgeted Revenue", default=0.0, store=True)
|
||||
hours = fields.Float("Timesheet Hour", digits=(16, 2), readonly=True, group_operator="sum")
|
||||
employee_price = fields.Float(string="Consultant Price")
|
||||
consultant_cost = fields.Float("Actual Cost")
|
||||
actual_revenue = fields.Float("Actual Revenue")
|
||||
profit = fields.Float('Profit', digits=(16, 2))
|
||||
profit_per = fields.Float('Porfit(%)', digits=(16, 2))
|
||||
# pricing_type = fields.Selection([
|
||||
# ('fixed_rate', 'Fixed rate'),
|
||||
# ('employee_rate', 'Consultant rate')
|
||||
# ], string="Pricing", readonly=True)
|
||||
# project_type = fields.Selection([
|
||||
# ('hours_in_consultant', 'Hours are budgeted according to a consultant'),
|
||||
# ('hours_no_limit', 'Total hours are budgeted without division to consultant'),
|
||||
# ], string="Project Type", readonly=True)
|
||||
|
||||
def init(self):
|
||||
'''Create the view'''
|
||||
tools.drop_view_if_exists(self._cr, self._table)
|
||||
self._cr.execute("""
|
||||
CREATE OR REPLACE VIEW %s AS (
|
||||
SELECT ROW_NUMBER() OVER() as id,
|
||||
aa.project_id AS project_id,
|
||||
aa.employee_id AS employee_id,
|
||||
bb.price_unit AS price_unit,
|
||||
bb.budgeted_qty AS budgeted_qty,
|
||||
bb.cost AS cost,
|
||||
bb.employee_price AS employee_price,
|
||||
SUM(aa.unit_amount) AS hours,
|
||||
(SUM(aa.unit_amount) * bb.employee_price) AS consultant_cost,
|
||||
(SUM(aa.unit_amount) * bb.price_unit) AS actual_revenue,
|
||||
((SUM(aa.unit_amount) * bb.price_unit)- (SUM(aa.unit_amount) * bb.employee_price)) AS profit,
|
||||
((((SUM(aa.unit_amount) * bb.price_unit)- (SUM(aa.unit_amount) * bb.employee_price))/(SUM(aa.unit_amount) * bb.price_unit))*100) AS profit_per
|
||||
FROM account_analytic_line aa
|
||||
Left JOIN project_sale_line_employee_map bb ON bb.project_id = aa.project_id and bb.employee_id = aa.employee_id
|
||||
GROUP BY aa.project_id, aa.employee_id,bb.price_unit,bb.budgeted_qty,bb.cost,bb.employee_price
|
||||
)""" % (self._table,))
|
|
@ -0,0 +1,79 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="cor_project_report_view_pivot" model="ir.ui.view">
|
||||
<field name="name">cor.project.report.pivot</field>
|
||||
<field name="model">cor.project.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Budget Analysis" disable_linking="True" sample="1"> <!-- display_quantity="true" -->
|
||||
<field name="project_id" type="col"/>
|
||||
<!--<field name="hours_type" type="col"/>-->
|
||||
<field name="hours" type="measure"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="cor_project_report_view_graph" model="ir.ui.view">
|
||||
<field name="name">cor.project.report.graph</field>
|
||||
<field name="model">cor.project.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="COR Project Report" type="bar" stacked="False" sample="1" disable_linking="1">
|
||||
<field name="project_id" type="row"/>
|
||||
<!--<field name="hours_type" type="row"/>-->
|
||||
<field name="hours" type="measure"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="cor_project_report_view_tree" model="ir.ui.view">
|
||||
<field name="name">cor.project.report.tree</field>
|
||||
<field name="model">cor.project.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="COR Project Report" create="false" edit="false" delete="false">
|
||||
<field name="project_id"/>
|
||||
<field name="employee_id"/>
|
||||
<field name="price_unit"/>
|
||||
<field name="budgeted_qty"/>
|
||||
<field name="cost"/>
|
||||
<field name="employee_price"/>
|
||||
<field name="hours"/>
|
||||
<field name="consultant_cost"/>
|
||||
<field name="actual_revenue"/>
|
||||
<field name="profit"/>
|
||||
<field name="profit_per"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="cor_project_report_view_search" model="ir.ui.view">
|
||||
<field name="name">cor.project.report.search</field>
|
||||
<field name="model">cor.project.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Project Report">
|
||||
<field name="project_id"/>
|
||||
<field name="employee_id"/>
|
||||
<field name="hours"/>
|
||||
<group expand="1" string="Group By">
|
||||
<filter string="Project" name="group_by_project" context="{'group_by':'project_id'}"/>
|
||||
<filter string="Consultant" name="group_by_employee_id" context="{'group_by':'employee_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="cor_project_report_view_action" model="ir.actions.act_window">
|
||||
<field name="name">COR Project Report</field>
|
||||
<field name="res_model">cor.project.report</field>
|
||||
<field name="view_mode">tree,pivot,graph</field>
|
||||
<field name="search_view_id" ref="cor_project_report_view_search"/>
|
||||
<field name="context">{'search_default_group_by_project': 1, 'default_res_model': 'cor.project.report'}</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_cor_project_report"
|
||||
parent="project.menu_project_report"
|
||||
action="cor_project_report_view_action"
|
||||
name="COR Project Report"
|
||||
sequence="50"/>
|
||||
|
||||
</odoo>
|
|
@ -158,6 +158,4 @@ class BudgetAmtAnalysis(models.Model):
|
|||
project_id,
|
||||
amount_type desc
|
||||
--group by Pro.id, PRO.partner_id, Pro.budgeted_revenue, AAL.amount
|
||||
)""" % (self._table,))
|
||||
|
||||
|
||||
)""" % (self._table,))
|
|
@ -89,4 +89,4 @@
|
|||
name="Projects Revenue Acutal Vs Budget"
|
||||
sequence="50"/>
|
||||
|
||||
</odoo>
|
||||
</odoo>
|
|
@ -0,0 +1,58 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields, models, tools
|
||||
|
||||
|
||||
class ProjectConsultantCustomReport(models.Model):
|
||||
|
||||
_name = "project.consultant.custom.report"
|
||||
_description = "Project Consultant Custom Analysis report"
|
||||
#_order = 'project_id'
|
||||
_auto = False
|
||||
|
||||
project_id = fields.Many2one('project.project', string='Project', readonly=True)
|
||||
parent_project = fields.Many2one('project.project', string='Parent Project', readonly=True)
|
||||
partner_id = fields.Many2one('res.partner', string='Client', readonly=True)
|
||||
employee_id = fields.Many2one('hr.employee', string='Consultant', readonly=True)
|
||||
start_date = fields.Date(string='Start Date', readonly=True)
|
||||
end_date = fields.Date(string='End Date', readonly=True)
|
||||
percentage = fields.Float("Budgeted Percentage (%)")
|
||||
budgeted_hours = fields.Float("Budgeted Hours for period", compute='_compute_budgeted_hours', store=True)
|
||||
actual_percentage = fields.Float("Actual Percentage (%)", compute='_compute_actual_calc', store=True)
|
||||
actual_hours = fields.Float("Actual Hours for period", compute='_compute_actual_calc', store=True)
|
||||
|
||||
def init(self):
|
||||
'''Create the view'''
|
||||
tools.drop_view_if_exists(self._cr, self._table)
|
||||
self._cr.execute("""
|
||||
CREATE OR REPLACE VIEW %s AS (
|
||||
SELECT ROW_NUMBER() OVER() as id,
|
||||
project_id,
|
||||
parentproject as parent_project,
|
||||
employee_id,
|
||||
partner_id,
|
||||
start_date,
|
||||
end_date,
|
||||
percentage,
|
||||
budgeted_hours,
|
||||
actual_percentage,
|
||||
actual_hours
|
||||
from (
|
||||
select pro.id AS project_id,
|
||||
(select project_id from project_subproject_rel as par where pro.id=par.id limit 1) as parentproject,
|
||||
pro.partner_id AS partner_id,
|
||||
consult.employee_id AS employee_id,
|
||||
consult.start_date as start_date,
|
||||
consult.end_date as end_date,
|
||||
consult.percentage percentage,
|
||||
consult.budgeted_hours AS budgeted_hours,
|
||||
consult.percentage AS actual_percentage,
|
||||
consult.actual_percentage AS actual_hours
|
||||
FROM project_project PRO
|
||||
right JOIN project_consultant_hrs consult ON PRO.id = consult.project_id
|
||||
WHERE PRO.active = 't' and PRO.pricing_type='employee_rate' and PRO.project_type='hours_in_consultant'
|
||||
) res
|
||||
)""" % (self._table,))
|
||||
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="project_consultant_custom_report_view_pivot" model="ir.ui.view">
|
||||
<field name="name">project.consultant.custom.report.pivot</field>
|
||||
<field name="model">project.consultant.custom.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Consultant Analysis" disable_linking="True" sample="1">
|
||||
<field name="project_id" type="row"/>
|
||||
<field name="percentage" type="measure"/>
|
||||
<field name="budgeted_hours" type="measure"/>
|
||||
<field name="actual_percentage" type="measure"/>
|
||||
<field name="actual_hours" type="measure"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="project_consultant_custom_report_view_graph" model="ir.ui.view">
|
||||
<field name="name">project.consultant.custom.report.graph</field>
|
||||
<field name="model">project.consultant.custom.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Consultant Analysis" type="bar" stacked="True" sample="1" disable_linking="1">
|
||||
<field name="project_id" type="col"/>
|
||||
<field name="budgeted_hours" type="row"/>
|
||||
<field name="actual_hours" type="row"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="project_consultant_custom_report_view_tree" model="ir.ui.view">
|
||||
<field name="name">project.consultant.custom.report.tree</field>
|
||||
<field name="model">project.consultant.custom.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Consultant Analysis" create="false" edit="false" delete="false">
|
||||
<field name="project_id"/>
|
||||
<field name="employee_id"/>
|
||||
<field name="start_date"/>
|
||||
<field name="end_date"/>
|
||||
<field name="percentage"/>
|
||||
<field name="budgeted_hours"/>
|
||||
<field name="actual_percentage"/>
|
||||
<field name="actual_hours"/>
|
||||
<field name="parent_project" optional="hide"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="project_consultant_custom_report_view_search" model="ir.ui.view">
|
||||
<field name="name">project.consultant.custom.report.search</field>
|
||||
<field name="model">project.consultant.custom.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Consultant Analysis">
|
||||
<field name="project_id"/>
|
||||
<field name="partner_id" filter_domain="[('partner_id', 'child_of', self)]"/>
|
||||
<field name="employee_id"/>
|
||||
<group expand="1" string="Group By">
|
||||
<filter string="Project" name="group_project" context="{'group_by':'project_id'}"/>
|
||||
<filter string="Consultant" name="group_employee" context="{'group_by':'employee_id'}"/>
|
||||
<filter string="Client" name="group_partner_id" context="{'group_by':'partner_id'}"/>
|
||||
<filter string="Start Date" name="group_startdate" domain="[]" context="{'group_by':'start_date:month'}"/>
|
||||
<filter string="End Date" name="group_enddate" domain="[]" context="{'group_by':'end_date:month'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="project_consultant_custom_report_action" model="ir.actions.act_window">
|
||||
<field name="name">Consultant Allocation Reports</field>
|
||||
<field name="res_model">project.consultant.custom.report</field>
|
||||
<field name="view_mode">pivot,tree,graph</field>
|
||||
<field name="search_view_id" ref="project_consultant_custom_report_view_search"/>
|
||||
<field name="context">{'search_default_group_project': 1,'search_default_group_employee': 1}</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_project_consultant_custom_report"
|
||||
parent="project.menu_project_report"
|
||||
action="project_consultant_custom_report_action"
|
||||
name="Consultant Allocation Reports"
|
||||
sequence="51"/>
|
||||
|
||||
</odoo>
|
|
@ -0,0 +1,264 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, fields, models, tools
|
||||
|
||||
class ProjectRevenueCustomReport(models.Model):
|
||||
|
||||
_name = "project.revenue.custom.report"
|
||||
_description = "Project Revenue Custom Analysis report"
|
||||
#_order = 'project_id'
|
||||
_auto = False
|
||||
|
||||
project_id = fields.Many2one('project.project', string='Project', readonly=True)
|
||||
parent_project = fields.Many2one('project.project', string='Parent Project', readonly=True)
|
||||
partner_id = fields.Many2one('res.partner', string='Client', readonly=True)
|
||||
pricing_type = fields.Selection([
|
||||
('fixed_rate', 'Fixed rate'),
|
||||
('employee_rate', 'Consultant rate')
|
||||
], string="Pricing", readonly=True)
|
||||
project_type = fields.Selection([
|
||||
('hours_in_consultant', 'Hours are budgeted according to a consultant'),
|
||||
('hours_no_limit', 'Total hours are budgeted without division to consultant'),
|
||||
], string="Project Type", readonly=True)
|
||||
employee_id = fields.Many2one('hr.employee', string='Consultant', readonly=True)
|
||||
#start_date = fields.Date(string='Start Date', readonly=True)
|
||||
#end_date = fields.Date(string='End Date', readonly=True)
|
||||
timesheet_sdatetime = fields.Datetime(string='Timesheet Start Time', readonly=True)
|
||||
unit_amount = fields.Float('Timesheet Hours', digits=(16, 2))
|
||||
timesheet_cost = fields.Float('Consultant Price', digits=(16, 2))
|
||||
profit_per = fields.Float(string='Profit (%)', digits=(16, 2))
|
||||
profit_amt = fields.Float(string='Profit Amount', digits=(16, 2))
|
||||
expenses_amt = fields.Float(string='Expenses Amount', digits=(16, 2))
|
||||
pro_hourly_rate = fields.Float("Hourly Rate", digits=(16, 2), group_operator="sum")
|
||||
budgeted_hours = fields.Float("Budgeted Hours", digits=(16, 2), readonly=True, group_operator="sum")
|
||||
budgeted_revenue = fields.Float("Budgeted Revenue", digits=(16, 2), readonly=True, group_operator="sum")
|
||||
actual_revenue = fields.Float("Actual Revenue", digits=(16, 2), readonly=True, group_operator="sum")
|
||||
actual_cost = fields.Float("Actual Cost", digits=(16, 2), readonly=True, group_operator="sum")
|
||||
overall_budgeted_revenue = fields.Float("Overall Budgeted Rev.", digits=(16, 2), readonly=True, group_operator="sum")
|
||||
overall_hourly_rate = fields.Float("Overall Hourly Rate", digits=(16, 2), group_operator="sum")
|
||||
|
||||
|
||||
"""def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True):
|
||||
if 'pro_hourly_rate' in fields:
|
||||
print("fields", fields)
|
||||
#fields.remove('pro_hourly_rate')
|
||||
res = super().read_group(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby, lazy=lazy)
|
||||
return res"""
|
||||
|
||||
def init(self):
|
||||
'''Create the view'''
|
||||
tools.drop_view_if_exists(self._cr, self._table)
|
||||
self._cr.execute("""
|
||||
CREATE OR REPLACE VIEW %s AS (
|
||||
SELECT ROW_NUMBER() OVER() as id,
|
||||
project_id,
|
||||
parentproject as parent_project,
|
||||
project_type,
|
||||
pricing_type,
|
||||
employee_id,
|
||||
overall_budgeted_revenue,
|
||||
partner_id,
|
||||
budgeted_revenue,
|
||||
budgeted_hours,
|
||||
pro_hourly_rate,
|
||||
overall_hourly_rate,
|
||||
actual_revenue,
|
||||
actual_cost,
|
||||
expenses_amt,
|
||||
profit_amt,
|
||||
profit_per,
|
||||
unit_amount,
|
||||
timesheet_cost,
|
||||
timesheet_sdatetime
|
||||
from (
|
||||
select pro.id AS project_id,
|
||||
(select project_id from project_subproject_rel as par where pro.id=par.id limit 1) as parentproject,
|
||||
pro.partner_id AS partner_id,
|
||||
pro.project_type AS project_type,
|
||||
pro.pricing_type as pricing_type,
|
||||
AAL.employee_id AS employee_id,
|
||||
0.0 AS overall_budgeted_revenue,
|
||||
0.0 AS budgeted_revenue,
|
||||
0.0 AS budgeted_hours,
|
||||
0.0 AS pro_hourly_rate,
|
||||
0.0 AS overall_hourly_rate,
|
||||
0.0 AS actual_revenue,
|
||||
(AAL.amount * -1) AS actual_cost,
|
||||
0.0 AS expenses_amt,
|
||||
0.0 - (AAL.amount * -1) AS profit_amt,
|
||||
0.0 AS profit_per,
|
||||
AAL.unit_amount,
|
||||
((AAL.amount * -1)/NULLIF(AAL.unit_amount, 0)) as timesheet_cost,
|
||||
AAL.start_datetime AS timesheet_sdatetime
|
||||
FROM project_project PRO
|
||||
RIGHT JOIN account_analytic_account AA ON PRO.analytic_account_id = AA.id
|
||||
RIGHT JOIN account_analytic_line AAL ON AAL.account_id = AA.id and AAL.project_id = PRO.id
|
||||
WHERE PRO.active = 't' and PRO.pricing_type = 'fixed_rate'
|
||||
UNION
|
||||
select
|
||||
pro.id AS project_id,
|
||||
(select project_id from project_subproject_rel as par where pro.id=par.id limit 1) as parentproject,
|
||||
pro.partner_id AS partner_id,
|
||||
pro.project_type AS project_type,
|
||||
pro.pricing_type as pricing_type,
|
||||
null::int AS employee_id,
|
||||
0.0 AS overall_budgeted_revenue,
|
||||
pro.budgeted_revenue AS budgeted_revenue,
|
||||
pro.budgeted_hours2 AS budgeted_hours,
|
||||
pro.hourly_rate AS pro_hourly_rate,
|
||||
0.0 AS overall_hourly_rate,
|
||||
0.0 AS actual_revenue,
|
||||
0.0 AS actual_cost,
|
||||
pro.expenses_amt AS expenses_amt,
|
||||
0.0 AS profit_amt,
|
||||
0.0 AS profit_per,
|
||||
0.0 as unit_amount,
|
||||
0.0 as timesheet_cost,
|
||||
null::timestamp as timesheet_sdatetime
|
||||
FROM project_project PRO
|
||||
WHERE PRO.active = 't' and PRO.pricing_type = 'employee_rate' and PRO.project_type='hours_no_limit'
|
||||
UNION
|
||||
select
|
||||
pro.id AS project_id,
|
||||
(select project_id from project_subproject_rel as par where pro.id=par.id limit 1) as parentproject,
|
||||
pro.partner_id AS partner_id,
|
||||
pro.project_type AS project_type,
|
||||
pro.pricing_type as pricing_type,
|
||||
AAL.employee_id AS employee_id,
|
||||
0.0 AS overall_budgeted_revenue,
|
||||
0.0 AS budgeted_revenue,
|
||||
0.0 AS budgeted_hours,
|
||||
0.0 AS pro_hourly_rate,
|
||||
0.0 AS overall_hourly_rate,
|
||||
(AAL.unit_amount * pro.hourly_rate) AS actual_revenue,
|
||||
(AAL.amount * -1) AS actual_cost,
|
||||
0.0 AS expenses_amt,
|
||||
((AAL.unit_amount * pro.hourly_rate) - (AAL.amount * -1)) AS profit_amt,
|
||||
((AAL.unit_amount * pro.hourly_rate) - (AAL.amount * -1))/NULLIF((AAL.unit_amount * pro.hourly_rate),0) AS profit_per,
|
||||
AAL.unit_amount,
|
||||
((AAL.amount * -1)/NULLIF(AAL.unit_amount, 0)) as timesheet_cost,
|
||||
AAL.start_datetime AS timesheet_sdatetime
|
||||
FROM project_project PRO
|
||||
RIGHT JOIN account_analytic_account AA ON PRO.analytic_account_id = AA.id
|
||||
RIGHT JOIN account_analytic_line AAL ON AAL.account_id = AA.id and AAL.project_id = PRO.id
|
||||
WHERE PRO.active = 't' and PRO.pricing_type = 'employee_rate' and PRO.project_type='hours_no_limit'
|
||||
UNION
|
||||
select
|
||||
pro.id AS project_id,
|
||||
(select project_id from project_subproject_rel as par where pro.id=par.id limit 1) as parentproject,
|
||||
pro.partner_id AS partner_id,
|
||||
pro.project_type AS project_type,
|
||||
pro.pricing_type as pricing_type,
|
||||
pro_emp.employee_id AS employee_id,
|
||||
0.0 AS overall_budgeted_revenue,
|
||||
pro_emp.cost AS budgeted_revenue,
|
||||
pro_emp.budgeted_qty AS budgeted_hours,
|
||||
COALESCE(pro_emp.price_unit, 0) as pro_hourly_rate,
|
||||
0.0 AS overall_hourly_rate,
|
||||
0.0 AS actual_revenue,
|
||||
0.0 AS actual_cost,
|
||||
0.0 AS expenses_amt,
|
||||
0.0 as profit_amt,
|
||||
0.0 as profit_per,
|
||||
0.0 as unit_amount,
|
||||
0.0 as timesheet_cost,
|
||||
null::timestamp as timesheet_sdatetime
|
||||
FROM project_project PRO
|
||||
Left JOIN project_sale_line_employee_map pro_emp ON pro_emp.project_id = pro.id
|
||||
LEFT JOIN account_analytic_account AA ON PRO.analytic_account_id = AA.id
|
||||
LEFT JOIN account_analytic_line AAL ON AAL.account_id = AA.id and AAL.project_id = PRO.id and AAL.employee_id = pro_emp.employee_id
|
||||
WHERE PRO.active = 't' and PRO.pricing_type='employee_rate' and PRO.project_type='hours_in_consultant'
|
||||
UNION
|
||||
select
|
||||
pro.id AS project_id,
|
||||
(select project_id from project_subproject_rel as par where pro.id=par.id limit 1) as parentproject,
|
||||
pro.partner_id AS partner_id,
|
||||
pro.project_type AS project_type,
|
||||
pro.pricing_type as pricing_type,
|
||||
null::int AS employee_id,
|
||||
pro.budgeted_revenue AS overall_budgeted_revenue,
|
||||
0.0 AS budgeted_revenue,
|
||||
0.0 AS budgeted_hours,
|
||||
0.0 as pro_hourly_rate,
|
||||
pro.hourly_rate AS overall_hourly_rate,
|
||||
0.0 AS actual_revenue,
|
||||
0.0 AS actual_cost,
|
||||
pro.expenses_amt AS expenses_amt,
|
||||
0.0 as profit_amt,
|
||||
0.0 as profit_per,
|
||||
0.0 as unit_amount,
|
||||
0.0 as timesheet_cost,
|
||||
null::timestamp as timesheet_sdatetime
|
||||
FROM project_project PRO
|
||||
WHERE PRO.active = 't' and PRO.pricing_type='employee_rate' and PRO.project_type='hours_in_consultant'
|
||||
UNION
|
||||
select
|
||||
pro.id AS project_id,
|
||||
(select project_id from project_subproject_rel as par where pro.id=par.id limit 1) as parentproject,
|
||||
pro.partner_id AS partner_id,
|
||||
pro.project_type AS project_type,
|
||||
pro.pricing_type as pricing_type,
|
||||
AAL.employee_id AS employee_id,
|
||||
0.0 AS overall_budgeted_revenue,
|
||||
0.0 AS budgeted_revenue,
|
||||
0.0 AS budgeted_hours,
|
||||
0.0 AS pro_hourly_rate,
|
||||
0.0 AS overall_hourly_rate,
|
||||
(AAL.unit_amount * pro_emp.price_unit) AS actual_revenue,
|
||||
case when pro_emp.employee_price is null then (AAL.amount * -1) else (AAL.unit_amount * pro_emp.employee_price) end as actual_cost,
|
||||
0.0 AS expenses_amt,
|
||||
(AAL.unit_amount * pro_emp.price_unit) - case when pro_emp.employee_price is null then (AAL.amount * -1) else (AAL.unit_amount * pro_emp.employee_price) end
|
||||
as profit_amt,
|
||||
(((AAL.unit_amount * pro_emp.price_unit) - case when pro_emp.employee_price is null then (AAL.amount * -1) else (AAL.unit_amount * pro_emp.employee_price) end)
|
||||
/ NULLIF((AAL.unit_amount * pro_emp.price_unit), 0)) * 100 as profit_per,
|
||||
AAL.unit_amount,
|
||||
case when pro_emp.employee_price is null then ((AAL.amount * -1)/NULLIF(AAL.unit_amount, 0)) else pro_emp.employee_price end as timesheet_cost,
|
||||
AAL.start_datetime AS timesheet_sdatetime
|
||||
FROM project_project PRO
|
||||
LEFT JOIN account_analytic_account AA ON PRO.analytic_account_id = AA.id
|
||||
LEFT JOIN account_analytic_line AAL ON AAL.account_id = AA.id and AAL.project_id = PRO.id
|
||||
Left JOIN project_sale_line_employee_map pro_emp ON pro_emp.project_id = pro.id and AAL.employee_id = pro_emp.employee_id
|
||||
LEFT JOIN hr_employee EMP ON AAL.employee_id = EMP.id
|
||||
WHERE PRO.active = 't' and PRO.pricing_type='employee_rate' and PRO.project_type='hours_in_consultant'
|
||||
) res
|
||||
)""" % (self._table,))
|
||||
|
||||
@api.model
|
||||
def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True):
|
||||
res = super(ProjectRevenueCustomReport, self).read_group(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby, lazy=lazy)
|
||||
hourly_rate = 0
|
||||
actual_cost = 0
|
||||
for line in res:
|
||||
try:
|
||||
if 'actual_cost' in line:
|
||||
actual_cost = line['actual_cost']
|
||||
if 'pro_hourly_rate' in line:
|
||||
hourly_rate = line['pro_hourly_rate']
|
||||
if 'unit_amount' in line: # and 'pro_hourly_rate' in line and 'id' in line
|
||||
if hourly_rate != 0:
|
||||
line['actual_revenue'] = hourly_rate * line['unit_amount']
|
||||
if 'unit_amount' in line and 'timesheet_cost' in line:
|
||||
line['actual_cost'] = line['timesheet_cost'] * line['unit_amount']
|
||||
if 'overall_budgeted_revenue' in line and 'budgeted_hours' in line:
|
||||
if line['budgeted_hours'] > 0:
|
||||
line['overall_hourly_rate'] = line['overall_budgeted_revenue'] / line['budgeted_hours']
|
||||
if 'pro_hourly_rate' in line and 'budgeted_hours' in line:
|
||||
if line['budgeted_hours'] > 0:
|
||||
line['pro_hourly_rate'] = line['budgeted_revenue'] / line['budgeted_hours']
|
||||
if 'actual_revenue' in line and 'actual_cost' in line and 'expenses_amt' in line:
|
||||
line['profit_amt'] = line['actual_revenue'] - line['actual_cost'] - line['expenses_amt']
|
||||
if 'profit_amt' in line and 'actual_revenue' in line:
|
||||
try:
|
||||
line['profit_per'] = (line['profit_amt'] / line['actual_revenue']) * 100
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
if 'unit_amount' in line:
|
||||
try:
|
||||
line['timesheet_cost'] = actual_cost / line['unit_amount']
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
return res
|
||||
|
|
@ -0,0 +1,255 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, fields, models, tools
|
||||
|
||||
class ProjectRevenueCustomReport2(models.Model):
|
||||
|
||||
_name = "project.revenue.custom.report2"
|
||||
_description = "Project Revenue Custom Analysis report2"
|
||||
#_order = 'project_id'
|
||||
_auto = False
|
||||
|
||||
project_id = fields.Many2one('project.project', string='Project', readonly=True)
|
||||
parent_project = fields.Many2one('project.project', string='Parent Project', readonly=True)
|
||||
partner_id = fields.Many2one('res.partner', string='Client', readonly=True)
|
||||
pricing_type = fields.Selection([
|
||||
('fixed_rate', 'Fixed rate'),
|
||||
('employee_rate', 'Consultant rate')
|
||||
], string="Pricing", readonly=True)
|
||||
project_type = fields.Selection([
|
||||
('hours_in_consultant', 'Hours are budgeted according to a consultant'),
|
||||
('hours_no_limit', 'Total hours are budgeted without division to consultant'),
|
||||
], string="Project Type", readonly=True)
|
||||
employee_id = fields.Many2one('hr.employee', string='Consultant', readonly=True)
|
||||
timesheet_sdatetime = fields.Datetime(string='Timesheet Start Time', readonly=True)
|
||||
unit_amount = fields.Float('Timesheet Hours', digits=(16, 2))
|
||||
timesheet_cost = fields.Float('Hourly Cost', digits=(16, 2))
|
||||
profit_per = fields.Float(string='Profit (%)', digits=(16, 2))
|
||||
profit_amt = fields.Float(string='Profit Amount', digits=(16, 2))
|
||||
expenses_amt = fields.Float(string='Expenses Amount', digits=(16, 2))
|
||||
pro_hourly_rate = fields.Float("Hourly Revenue", digits=(16, 2), group_operator="max")
|
||||
budgeted_hours = fields.Float("Budgeted Hours", digits=(16, 2), readonly=True, group_operator="sum")
|
||||
budgeted_revenue = fields.Float("Budgeted Revenue", digits=(16, 2), readonly=True, group_operator="sum")
|
||||
actual_revenue = fields.Float("Actual Revenue", digits=(16, 2), readonly=True, group_operator="sum")
|
||||
actual_cost = fields.Float("Actual Cost", digits=(16, 2), readonly=True, group_operator="sum")
|
||||
overall_budgeted_revenue = fields.Float("Overall Budgeted Rev.", digits=(16, 2), readonly=True, group_operator="sum")
|
||||
overall_hourly_rate = fields.Float("Overall Hourly Rate", digits=(16, 2), group_operator="sum")
|
||||
|
||||
|
||||
def init(self):
|
||||
'''Create the view'''
|
||||
tools.drop_view_if_exists(self._cr, self._table)
|
||||
self._cr.execute("""
|
||||
CREATE OR REPLACE VIEW %s AS (
|
||||
SELECT ROW_NUMBER() OVER() as id,
|
||||
project_id,
|
||||
parentproject as parent_project,
|
||||
project_type,
|
||||
pricing_type,
|
||||
employee_id,
|
||||
overall_budgeted_revenue,
|
||||
partner_id,
|
||||
budgeted_revenue,
|
||||
budgeted_hours,
|
||||
pro_hourly_rate,
|
||||
overall_hourly_rate,
|
||||
actual_revenue,
|
||||
actual_cost,
|
||||
expenses_amt,
|
||||
profit_amt,
|
||||
profit_per,
|
||||
unit_amount,
|
||||
timesheet_cost,
|
||||
timesheet_sdatetime
|
||||
from (
|
||||
select pro.id AS project_id,
|
||||
(select project_id from project_subproject_rel as par where pro.id=par.id limit 1) as parentproject,
|
||||
pro.partner_id AS partner_id,
|
||||
pro.project_type AS project_type,
|
||||
pro.pricing_type as pricing_type,
|
||||
AAL.employee_id AS employee_id,
|
||||
0.0 AS overall_budgeted_revenue,
|
||||
0.0 AS budgeted_revenue,
|
||||
0.0 AS budgeted_hours,
|
||||
0.0 AS overall_hourly_rate,
|
||||
AAL.unit_amount,
|
||||
0.0 AS pro_hourly_rate,
|
||||
((AAL.amount * -1)/NULLIF(AAL.unit_amount, 0)) as timesheet_cost,
|
||||
0.0 AS actual_revenue,
|
||||
(AAL.amount * -1) AS actual_cost,
|
||||
0.0 AS expenses_amt,
|
||||
0.0 - (AAL.amount * -1) AS profit_amt,
|
||||
0.0 AS profit_per,
|
||||
AAL.start_datetime AS timesheet_sdatetime
|
||||
FROM project_project PRO
|
||||
RIGHT JOIN account_analytic_account AA ON PRO.analytic_account_id = AA.id
|
||||
RIGHT JOIN account_analytic_line AAL ON AAL.account_id = AA.id and AAL.project_id = PRO.id
|
||||
WHERE PRO.active = 't' and PRO.pricing_type = 'fixed_rate'
|
||||
UNION
|
||||
select
|
||||
pro.id AS project_id,
|
||||
(select project_id from project_subproject_rel as par where pro.id=par.id limit 1) as parentproject,
|
||||
pro.partner_id AS partner_id,
|
||||
pro.project_type AS project_type,
|
||||
pro.pricing_type as pricing_type,
|
||||
null::int AS employee_id,
|
||||
0.0 AS overall_budgeted_revenue,
|
||||
pro.budgeted_revenue AS budgeted_revenue,
|
||||
pro.budgeted_hours2 AS budgeted_hours,
|
||||
0.0 AS overall_hourly_rate,
|
||||
0.0 as unit_amount,
|
||||
0.0 AS pro_hourly_rate,
|
||||
0.0 as timesheet_cost,
|
||||
0.0 AS actual_revenue,
|
||||
0.0 AS actual_cost,
|
||||
pro.expenses_amt AS expenses_amt,
|
||||
0.0 AS profit_amt,
|
||||
0.0 AS profit_per,
|
||||
null::timestamp as timesheet_sdatetime
|
||||
FROM project_project PRO
|
||||
WHERE PRO.active = 't' and PRO.pricing_type = 'employee_rate' and PRO.project_type='hours_no_limit'
|
||||
UNION
|
||||
select
|
||||
pro.id AS project_id,
|
||||
(select project_id from project_subproject_rel as par where pro.id=par.id limit 1) as parentproject,
|
||||
pro.partner_id AS partner_id,
|
||||
pro.project_type AS project_type,
|
||||
pro.pricing_type as pricing_type,
|
||||
AAL.employee_id AS employee_id,
|
||||
0.0 AS overall_budgeted_revenue,
|
||||
0.0 AS budgeted_revenue,
|
||||
0.0 AS budgeted_hours,
|
||||
0.0 AS overall_hourly_rate,
|
||||
AAL.unit_amount,
|
||||
pro.hourly_rate AS pro_hourly_rate,
|
||||
((AAL.amount * -1)/NULLIF(AAL.unit_amount, 0)) as timesheet_cost,
|
||||
(AAL.unit_amount * pro.hourly_rate) AS actual_revenue,
|
||||
(AAL.amount * -1) AS actual_cost,
|
||||
0.0 AS expenses_amt,
|
||||
((AAL.unit_amount * pro.hourly_rate) - (AAL.amount * -1)) AS profit_amt,
|
||||
((AAL.unit_amount * pro.hourly_rate) - (AAL.amount * -1))/NULLIF((AAL.unit_amount * pro.hourly_rate),0) AS profit_per,
|
||||
AAL.start_datetime AS timesheet_sdatetime
|
||||
FROM project_project PRO
|
||||
RIGHT JOIN account_analytic_account AA ON PRO.analytic_account_id = AA.id
|
||||
RIGHT JOIN account_analytic_line AAL ON AAL.account_id = AA.id and AAL.project_id = PRO.id
|
||||
WHERE PRO.active = 't' and PRO.pricing_type = 'employee_rate' and PRO.project_type='hours_no_limit'
|
||||
UNION
|
||||
select
|
||||
pro.id AS project_id,
|
||||
(select project_id from project_subproject_rel as par where pro.id=par.id limit 1) as parentproject,
|
||||
pro.partner_id AS partner_id,
|
||||
pro.project_type AS project_type,
|
||||
pro.pricing_type as pricing_type,
|
||||
pro_emp.employee_id AS employee_id,
|
||||
0.0 AS overall_budgeted_revenue,
|
||||
pro_emp.cost AS budgeted_revenue,
|
||||
pro_emp.budgeted_qty AS budgeted_hours,
|
||||
0.0 as timesheet_cost,
|
||||
0.0 AS overall_hourly_rate,
|
||||
0.0 as unit_amount,
|
||||
0.0 AS pro_hourly_rate,
|
||||
0.0 AS actual_revenue,
|
||||
0.0 AS actual_cost,
|
||||
0.0 AS expenses_amt,
|
||||
0.0 as profit_amt,
|
||||
0.0 as profit_per,
|
||||
null::timestamp as timesheet_sdatetime
|
||||
FROM project_project PRO
|
||||
Left JOIN project_sale_line_employee_map pro_emp ON pro_emp.project_id = pro.id
|
||||
LEFT JOIN account_analytic_account AA ON PRO.analytic_account_id = AA.id
|
||||
LEFT JOIN account_analytic_line AAL ON AAL.account_id = AA.id and AAL.project_id = PRO.id and AAL.employee_id = pro_emp.employee_id
|
||||
WHERE PRO.active = 't' and PRO.pricing_type='employee_rate' and PRO.project_type='hours_in_consultant'
|
||||
UNION
|
||||
select
|
||||
pro.id AS project_id,
|
||||
(select project_id from project_subproject_rel as par where pro.id=par.id limit 1) as parentproject,
|
||||
pro.partner_id AS partner_id,
|
||||
pro.project_type AS project_type,
|
||||
pro.pricing_type as pricing_type,
|
||||
null::int AS employee_id,
|
||||
pro.budgeted_revenue AS overall_budgeted_revenue,
|
||||
0.0 AS budgeted_revenue,
|
||||
0.0 AS budgeted_hours,
|
||||
pro.hourly_rate AS overall_hourly_rate,
|
||||
0.0 as unit_amount,
|
||||
0.0 as pro_hourly_rate,
|
||||
0.0 as timesheet_cost,
|
||||
0.0 AS actual_revenue,
|
||||
0.0 AS actual_cost,
|
||||
pro.expenses_amt AS expenses_amt,
|
||||
0.0 as profit_amt,
|
||||
0.0 as profit_per,
|
||||
null::timestamp as timesheet_sdatetime
|
||||
FROM project_project PRO
|
||||
WHERE PRO.active = 't' and PRO.pricing_type='employee_rate' and PRO.project_type='hours_in_consultant'
|
||||
UNION
|
||||
select
|
||||
pro.id AS project_id,
|
||||
(select project_id from project_subproject_rel as par where pro.id=par.id limit 1) as parentproject,
|
||||
pro.partner_id AS partner_id,
|
||||
pro.project_type AS project_type,
|
||||
pro.pricing_type as pricing_type,
|
||||
AAL.employee_id AS employee_id,
|
||||
0.0 AS overall_budgeted_revenue,
|
||||
0.0 AS budgeted_revenue,
|
||||
0.0 AS budgeted_hours,
|
||||
0.0 AS overall_hourly_rate,
|
||||
AAL.unit_amount,
|
||||
COALESCE(pro_emp.price_unit, 0) as pro_hourly_rate,
|
||||
case when pro_emp.employee_price is null then ((AAL.amount * -1)/NULLIF(AAL.unit_amount, 0)) else pro_emp.employee_price end as timesheet_cost,
|
||||
(AAL.unit_amount * pro_emp.price_unit) AS actual_revenue,
|
||||
case when pro_emp.employee_price is null then (AAL.amount * -1) else (AAL.unit_amount * pro_emp.employee_price) end as actual_cost,
|
||||
0.0 AS expenses_amt,
|
||||
(AAL.unit_amount * pro_emp.price_unit) - case when pro_emp.employee_price is null then (AAL.amount * -1) else (AAL.unit_amount * pro_emp.employee_price) end
|
||||
as profit_amt,
|
||||
(((AAL.unit_amount * pro_emp.price_unit) - case when pro_emp.employee_price is null then (AAL.amount * -1) else (AAL.unit_amount * pro_emp.employee_price) end)
|
||||
/ NULLIF((AAL.unit_amount * pro_emp.price_unit), 0)) * 100 as profit_per,
|
||||
AAL.start_datetime AS timesheet_sdatetime
|
||||
FROM project_project PRO
|
||||
LEFT JOIN account_analytic_account AA ON PRO.analytic_account_id = AA.id
|
||||
LEFT JOIN account_analytic_line AAL ON AAL.account_id = AA.id and AAL.project_id = PRO.id
|
||||
Left JOIN project_sale_line_employee_map pro_emp ON pro_emp.project_id = pro.id and AAL.employee_id = pro_emp.employee_id
|
||||
LEFT JOIN hr_employee EMP ON AAL.employee_id = EMP.id
|
||||
WHERE PRO.active = 't' and PRO.pricing_type='employee_rate' and PRO.project_type='hours_in_consultant'
|
||||
) res
|
||||
)""" % (self._table,))
|
||||
|
||||
@api.model
|
||||
def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True):
|
||||
res = super(ProjectRevenueCustomReport2, self).read_group(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby, lazy=lazy)
|
||||
hourly_rate = 0
|
||||
actual_cost = 0
|
||||
for line in res:
|
||||
try:
|
||||
if 'actual_cost' in line:
|
||||
actual_cost = line['actual_cost']
|
||||
"""if 'pro_hourly_rate' in line:
|
||||
hourly_rate = line['pro_hourly_rate']
|
||||
if 'unit_amount' in line: # and 'pro_hourly_rate' in line and 'id' in line
|
||||
if hourly_rate != 0:
|
||||
line['actual_revenue'] = hourly_rate * line['unit_amount']
|
||||
if 'unit_amount' in line and 'timesheet_cost' in line:
|
||||
line['actual_cost'] = line['timesheet_cost'] * line['unit_amount']"""
|
||||
if 'overall_budgeted_revenue' in line and 'budgeted_hours' in line:
|
||||
if line['budgeted_hours'] > 0:
|
||||
line['overall_hourly_rate'] = line['overall_budgeted_revenue'] / line['budgeted_hours']
|
||||
if 'pro_hourly_rate' in line and 'budgeted_hours' in line:
|
||||
if line['budgeted_hours'] > 0:
|
||||
line['pro_hourly_rate'] = line['budgeted_revenue'] / line['budgeted_hours']
|
||||
if 'actual_revenue' in line and 'actual_cost' in line and 'expenses_amt' in line:
|
||||
line['profit_amt'] = line['actual_revenue'] - line['actual_cost'] - line['expenses_amt']
|
||||
if 'profit_amt' in line and 'actual_revenue' in line:
|
||||
try:
|
||||
line['profit_per'] = (line['profit_amt'] / line['actual_revenue']) * 100
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
if 'unit_amount' in line:
|
||||
try:
|
||||
line['timesheet_cost'] = actual_cost / line['unit_amount']
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
return res
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="project_revenue_custom_report2_view_pivot" model="ir.ui.view">
|
||||
<field name="name">project.revenue.custom.report2.pivot</field>
|
||||
<field name="model">project.revenue.custom.report2</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Revenue Analysis" disable_linking="True" sample="1">
|
||||
<field name="project_id" type="row"/>
|
||||
<field name="overall_budgeted_revenue" type="measure"/>
|
||||
<field name="budgeted_revenue" type="measure"/>
|
||||
<field name="actual_revenue" type="measure"/>
|
||||
<field name="actual_cost" type="measure"/>
|
||||
<field name="budgeted_hours" type="measure"/>
|
||||
<field name="overall_hourly_rate" type="measure"/>
|
||||
<field name="pro_hourly_rate" type="measure"/>
|
||||
<field name="expenses_amt" type="measure"/>
|
||||
<field name="profit_amt" type="measure"/>
|
||||
<field name="profit_per" type="measure"/>
|
||||
<field name="unit_amount" type="measure"/>
|
||||
<field name="timesheet_cost" type="measure"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="project_revenue_custom_report2_view_graph" model="ir.ui.view">
|
||||
<field name="name">project.revenue.custom.report2.graph</field>
|
||||
<field name="model">project.revenue.custom.report2</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Revenue Analysis" type="bar" stacked="True" sample="1" disable_linking="1">
|
||||
<field name="project_id" type="col"/>
|
||||
<field name="budgeted_revenue" type="row"/>
|
||||
<field name="actual_revenue" type="row"/>
|
||||
<field name="actual_cost" type="row"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="project_revenue_custom_report2_view_tree" model="ir.ui.view">
|
||||
<field name="name">project.revenue.custom.report2.tree</field>
|
||||
<field name="model">project.revenue.custom.report2</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Revenue Analysis" create="false" edit="false" delete="false">
|
||||
<field name="project_id"/>
|
||||
<field name="employee_id"/>
|
||||
<field name="budgeted_revenue"/>
|
||||
<field name="actual_revenue"/>
|
||||
<field name="actual_cost"/>
|
||||
<field name="budgeted_hours"/>
|
||||
<field name="pro_hourly_rate"/>
|
||||
<field name="profit_amt"/>
|
||||
<field name="profit_per"/>
|
||||
<field name="unit_amount"/>
|
||||
<field name="timesheet_cost"/>
|
||||
<field name="parent_project" optional="hide"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="project_revenue_custom_report2_view_search" model="ir.ui.view">
|
||||
<field name="name">project.revenue.custom.report2.search</field>
|
||||
<field name="model">project.revenue.custom.report2</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Revenue Analysis">
|
||||
<field name="project_id"/>
|
||||
<field name="partner_id" filter_domain="[('partner_id', 'child_of', self)]"/>
|
||||
<field name="employee_id"/>
|
||||
<filter string="Fixed rate" name="fixed" domain="[('pricing_type','=','fixed_rate')]"/>
|
||||
<filter string="Hours are budgeted according to a consultant" name="cons" domain="[('pricing_type','=','employee_rate'),('project_type','=','hours_in_consultant')]"/>
|
||||
<filter string="Total hours are budgeted without division to consultant" name="limit" domain="[('pricing_type','=','employee_rate'),('project_type','=','hours_no_limit')]"/>
|
||||
<filter string="Not Fixed rate" name="notfixed" domain="[('pricing_type','!=','fixed_rate')]"/>
|
||||
<filter string="Timesheet Date" name="filter_date_from" date="timesheet_sdatetime"/>
|
||||
<group expand="1" string="Group By">
|
||||
<filter string="Project" name="group_project" context="{'group_by':'project_id'}"/>
|
||||
<filter string="Consultant" name="group_employee" context="{'group_by':'employee_id'}"/>
|
||||
<filter string="Client" name="group_partner_id" context="{'group_by':'partner_id'}"/>
|
||||
<filter string="Timesheet Date" name="group_t_starttime" domain="[]" context="{'group_by':'timesheet_sdatetime:month'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="project_revenue_custom_report2_action" model="ir.actions.act_window">
|
||||
<field name="name">Projects Revenue</field>
|
||||
<field name="res_model">project.revenue.custom.report2</field>
|
||||
<field name="view_mode">pivot,tree,graph</field>
|
||||
<field name="search_view_id" ref="project_revenue_custom_report2_view_search"/>
|
||||
<field name="context">{'search_default_group_project': 1,'search_default_group_employee': 1,'search_default_group_t_starttime': 1}</field>
|
||||
</record>
|
||||
|
||||
<!--<menuitem id="menu_project_revenue_custom_report2"
|
||||
parent="project.menu_project_report"
|
||||
action="project_revenue_custom_report2_action"
|
||||
name="Projects Revenue (1.1)"
|
||||
sequence="50"/>-->
|
||||
<menuitem id="menu_project_revenue_custom_report2"
|
||||
parent="project.menu_project_report"
|
||||
action="project_revenue_custom_report2_action"
|
||||
name="Projects Revenue"
|
||||
sequence="50"/>
|
||||
|
||||
</odoo>
|
|
@ -0,0 +1,97 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="project_revenue_custom_report_view_pivot" model="ir.ui.view">
|
||||
<field name="name">project.revenue.custom.report.pivot</field>
|
||||
<field name="model">project.revenue.custom.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Revenue Analysis" disable_linking="True" sample="1">
|
||||
<field name="project_id" type="row"/>
|
||||
<field name="overall_budgeted_revenue" type="measure"/>
|
||||
<field name="budgeted_revenue" type="measure"/>
|
||||
<field name="actual_revenue" type="measure"/>
|
||||
<field name="actual_cost" type="measure"/>
|
||||
<field name="budgeted_hours" type="measure"/>
|
||||
<field name="overall_hourly_rate" type="measure"/>
|
||||
<field name="pro_hourly_rate" type="measure"/>
|
||||
<field name="expenses_amt" type="measure"/>
|
||||
<field name="profit_amt" type="measure"/>
|
||||
<field name="profit_per" type="measure"/>
|
||||
<field name="unit_amount" type="measure"/>
|
||||
<field name="timesheet_cost" type="measure"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="project_revenue_custom_report_view_graph" model="ir.ui.view">
|
||||
<field name="name">project.revenue.custom.report.graph</field>
|
||||
<field name="model">project.revenue.custom.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Revenue Analysis" type="bar" stacked="True" sample="1" disable_linking="1">
|
||||
<field name="project_id" type="col"/>
|
||||
<field name="budgeted_revenue" type="row"/>
|
||||
<field name="actual_revenue" type="row"/>
|
||||
<field name="actual_cost" type="row"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="project_revenue_custom_report_view_tree" model="ir.ui.view">
|
||||
<field name="name">project.revenue.custom.report.tree</field>
|
||||
<field name="model">project.revenue.custom.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Revenue Analysis" create="false" edit="false" delete="false">
|
||||
<field name="project_id"/>
|
||||
<field name="employee_id"/>
|
||||
<field name="budgeted_revenue"/>
|
||||
<field name="actual_revenue"/>
|
||||
<field name="actual_cost"/>
|
||||
<field name="budgeted_hours"/>
|
||||
<field name="pro_hourly_rate"/>
|
||||
<field name="profit_amt"/>
|
||||
<field name="profit_per"/>
|
||||
<field name="unit_amount"/>
|
||||
<field name="timesheet_cost"/>
|
||||
<field name="parent_project" optional="hide"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="project_revenue_custom_report_view_search" model="ir.ui.view">
|
||||
<field name="name">project.revenue.custom.report.search</field>
|
||||
<field name="model">project.revenue.custom.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Revenue Analysis">
|
||||
<field name="project_id"/>
|
||||
<field name="partner_id" filter_domain="[('partner_id', 'child_of', self)]"/>
|
||||
<field name="employee_id"/>
|
||||
<filter string="Fixed rate" name="fixed" domain="[('pricing_type','=','fixed_rate')]"/>
|
||||
<filter string="Hours are budgeted according to a consultant" name="cons" domain="[('pricing_type','=','employee_rate'),('project_type','=','hours_in_consultant')]"/>
|
||||
<filter string="Total hours are budgeted without division to consultant" name="limit" domain="[('pricing_type','=','employee_rate'),('project_type','=','hours_no_limit')]"/>
|
||||
<filter string="Not Fixed rate" name="notfixed" domain="[('pricing_type','!=','fixed_rate')]"/>
|
||||
<group expand="1" string="Group By">
|
||||
<filter string="Project" name="group_project" context="{'group_by':'project_id'}"/>
|
||||
<filter string="Consultant" name="group_employee" context="{'group_by':'employee_id'}"/>
|
||||
<filter string="Client" name="group_partner_id" context="{'group_by':'partner_id'}"/>
|
||||
<filter string="Timesheet Date" name="group_t_starttime" domain="[]" context="{'group_by':'timesheet_sdatetime:month'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="project_revenue_custom_report_action" model="ir.actions.act_window">
|
||||
<field name="name">Projects Revenue</field>
|
||||
<field name="res_model">project.revenue.custom.report</field>
|
||||
<field name="view_mode">pivot,tree,graph</field>
|
||||
<field name="search_view_id" ref="project_revenue_custom_report_view_search"/>
|
||||
<field name="context">{'search_default_group_project': 1,'search_default_group_employee': 1,'search_default_group_t_starttime': 1}</field>
|
||||
</record>
|
||||
|
||||
<!--<menuitem id="menu_project_revenue_custom_report"
|
||||
parent="project.menu_project_report"
|
||||
action="project_revenue_custom_report_action"
|
||||
name="Projects Revenue"
|
||||
sequence="50"/>-->
|
||||
|
||||
</odoo>
|
|
@ -8,4 +8,12 @@ access_project_create_expense_user,access_project_create_expense_project_user,mo
|
|||
access_project_timeline_report_manager,project.timeline.report,model_project_timeline_report,project.group_project_manager,1,1,1,1
|
||||
access_project_timeline_report_user,project.timeline.report,model_project_timeline_report,project.group_project_user,1,0,0,0
|
||||
access_project_timesheet_report_manager,project.timesheet.report,model_project_timesheet_report,project.group_project_manager,1,1,1,1
|
||||
access_project_timesheet_report_user,project.timesheet.report,model_project_timesheet_report,project.group_project_user,1,0,0,0
|
||||
access_project_timesheet_report_user,project.timesheet.report,model_project_timesheet_report,project.group_project_user,1,0,0,0
|
||||
access_project_revenue_custom_report_manager,project_revenue_custom_report_manager,model_project_revenue_custom_report,project.group_project_manager,1,1,1,1
|
||||
access_project_revenue_custom_report_user,project_revenue_custom_report_user,model_project_revenue_custom_report,project.group_project_user,1,0,0,0
|
||||
access_project_consultant_custom_report_manager,project_consultant_custom_report_manager,model_project_consultant_custom_report,project.group_project_manager,1,1,1,1
|
||||
access_project_consultant_custom_report_user,project_consultant_custom_report_user,model_project_consultant_custom_report,project.group_project_user,1,0,0,0
|
||||
access_project_revenue_custom_report2_manager,project_revenue_custom_report2_manager,model_project_revenue_custom_report2,project.group_project_manager,1,1,1,1
|
||||
access_project_revenue_custom_report2_user,project_revenue_custom_report2_user,model_project_revenue_custom_report2,project.group_project_user,1,0,0,0
|
||||
|
||||
|
||||
|
|
|
|
@ -0,0 +1,14 @@
|
|||
Sticky Pivot View V14
|
||||
======================
|
||||
|
||||
This module will helps to stick the pivot view header (Row and Column) .
|
||||
|
||||
|
||||
Credits
|
||||
-------
|
||||
* Developer:
|
||||
(v14) Shahil @ Cybrosys
|
||||
|
||||
Contacts
|
||||
--------
|
||||
* Mail Contact : odoo@cybrosys.com
|
|
@ -0,0 +1,45 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#############################################################################
|
||||
#
|
||||
# Cybrosys Technologies Pvt. Ltd.
|
||||
#
|
||||
# Copyright (C) 2021-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
||||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
|
||||
#
|
||||
# You can modify it under the terms of the GNU LESSER
|
||||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
# (LGPL v3) along with this program.
|
||||
# If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
{
|
||||
'name': 'Sticky Pivot View',
|
||||
'version': '14.0.1.0.0',
|
||||
'summary': 'Helps to stick the pivot view (Row and Column)',
|
||||
'description': 'Helps to stick the pivot view (Row and Column)',
|
||||
'category': 'Tools',
|
||||
'author': 'Cybrosys Techno Solutions',
|
||||
'company': 'Cybrosys Techno Solutions',
|
||||
'maintainer': 'Cybrosys Techno Solutions',
|
||||
'website': 'https://www.cybrosys.com',
|
||||
'license': 'LGPL-3',
|
||||
'images': ['static/description/banner.png'],
|
||||
'depends': ['base', 'web'],
|
||||
'qweb': [
|
||||
'static/src/xml/pivot.xml',
|
||||
],
|
||||
'data': [
|
||||
'views/assets.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'application': False,
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
## Module <sticky_pivot_view>
|
||||
|
||||
#### 13.08.2021
|
||||
#### Version 14.0.1.0.0
|
||||
#### ADD Initial Commit for sticky_pivot_view
|
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 733 B |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 673 B |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 905 B |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 627 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 988 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 61 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 176 KiB |
After Width: | Height: | Size: 108 KiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 14 KiB |
|
@ -0,0 +1,531 @@
|
|||
<div class="container" style="padding: 1rem !important; margin-bottom: 1rem !important;">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-12 col-lg-12 d-flex justify-content-between"
|
||||
style="border-bottom: 1px solid #d5d5d5;">
|
||||
<div class="my-3">
|
||||
<img src="./assets/icons/logo.png" style="width: auto !important; height: 40px !important;">
|
||||
</div>
|
||||
<div class="my-3 d-flex align-items-center">
|
||||
<div
|
||||
style="background-color: #7C7BAD !important; color: #fff !important; font-weight: 600 !important; padding: 5px 15px 8px !important; margin: 0 5px !important;">
|
||||
<i class="fa fa-check mr-1"></i>Community
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container" style="padding: 0rem 1.5rem 4rem !important">
|
||||
<div class="row" style="height: 900px !important;">
|
||||
<div class="col-sm-12 col-md-12 col-lg-12"
|
||||
style="padding: 4rem 1rem !important; background-color: #714B67 !important; height: 600px !important; border-radius: 20px !important;">
|
||||
<h1
|
||||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #FFFFFF !important; font-size: 3.5rem !important; text-align: center !important;">
|
||||
Sticky Pivot View</h1>
|
||||
<p
|
||||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 300 !important; color: #FFFFFF !important; font-size: 1.4rem !important; text-align: center !important;">
|
||||
Helps to stick the pivot view while scrolling Horizontally and Vertically
|
||||
</p>
|
||||
<img src="./assets/screenshots/hero.png" class="img-responsive" width="100%" height="auto" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12" style="border-bottom: 1px solid #d5d5d5 !important; margin-bottom: 2rem !important">
|
||||
<h2
|
||||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;">
|
||||
<i class="fa fa-compass mr-2"></i>Explore this module
|
||||
</h2>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<a href="#overview" style="text-decoration: none !important;">
|
||||
<div class="row"
|
||||
style="background-color: #f5f2f5 !important; border-radius: 10px !important; margin: 1rem !important; padding: 1.5em !important; height: 100px !important;">
|
||||
<div class="col-8">
|
||||
<h3
|
||||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.2rem !important;">
|
||||
Overview</h3>
|
||||
<p
|
||||
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #714B67 !important; font-size: 0.9rem !important;">
|
||||
Learn more about this module</p>
|
||||
</div>
|
||||
<div class="col-4 text-right d-flex justify-content-end align-items-center">
|
||||
<i class="fa fa-chevron-right" style="color: #714B67 !important;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<a href="#features" style="text-decoration: none !important;">
|
||||
<div class="row"
|
||||
style="background-color: #f5f2f5 !important; border-radius: 10px !important; margin: 1rem !important; padding: 1.5em !important; height: 100px !important;">
|
||||
<div class="col-8">
|
||||
<h3
|
||||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.2rem !important;">
|
||||
Features</h3>
|
||||
<p
|
||||
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #714B67 !important; font-size: 0.9rem !important;">
|
||||
View features of this module</p>
|
||||
</div>
|
||||
<div class="col-4 text-right d-flex justify-content-end align-items-center">
|
||||
<i class="fa fa-chevron-right" style="color: #714B67 !important;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<a href="#screenshots" style="text-decoration: none !important;">
|
||||
<div class="row"
|
||||
style="background-color: #f5f2f5 !important; border-radius: 10px !important; margin: 1rem !important; padding: 1.5em !important; height: 100px !important;">
|
||||
<div class="col-8">
|
||||
<h3
|
||||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.2rem !important;">
|
||||
Screenshots</h3>
|
||||
<p
|
||||
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #714B67 !important; font-size: 0.9rem !important;">
|
||||
See key screenshots of this module</p>
|
||||
</div>
|
||||
<div class="col-4 text-right d-flex justify-content-end align-items-center">
|
||||
<i class="fa fa-chevron-right" style="color: #714B67 !important;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row" id="overview">
|
||||
<div class="col-md-12" style="border-bottom: 1px solid #d5d5d5 !important; margin: 2rem 0 !important">
|
||||
<h2
|
||||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;">
|
||||
<i class="fa fa-pie-chart mr-2"></i>Overview
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="col-mg-12 pl-3">
|
||||
<p
|
||||
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important; line-height: 30px !important;">
|
||||
This module will ensure sticky pivot view and enhance the user experience so that the user will
|
||||
never lose the headers while scrolling (Horizontally and Vertically) the report.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row" id="features">
|
||||
<div class="col-md-12" style="border-bottom: 1px solid #d5d5d5 !important; margin: 2rem 0 !important">
|
||||
<h2
|
||||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;">
|
||||
<i class="fa fa-star mr-2"></i>Features
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 pl-3 d-flex">
|
||||
<div>
|
||||
<img src="assets/icons/check.png">
|
||||
</div>
|
||||
<div>
|
||||
<h4
|
||||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;">
|
||||
Helps to stick the pivot view while scrolling</h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row" id="screenshots">
|
||||
<div class="col-md-12" style="border-bottom: 1px solid #d5d5d5 !important; margin: 2rem 0 !important">
|
||||
<h2
|
||||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;">
|
||||
<i class="fa fa-image mr-2"></i>Screenshots
|
||||
</h2>
|
||||
</div>
|
||||
<div class="col-lg-12 my-2">
|
||||
<h4 class="mt-2"
|
||||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;">
|
||||
Sticky header in pivot view</h4>
|
||||
<p
|
||||
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;">
|
||||
Helps to stick the pivot view while scrolling Horizontally and Vertically</p>
|
||||
<img src="assets/screenshots/sticky_pivot_view.png" class="img-responsive img-thumbnail border" width="100%"
|
||||
height="auto" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SUGGESTED PRODUCTS -->
|
||||
<div class="row">
|
||||
<div class="col-lg-12 d-flex flex-column justify-content-center"
|
||||
style="text-align: center; padding: 2.5rem 1rem !important;">
|
||||
<h2 style="color: #212529 !important;">Suggested Products</h2>
|
||||
<hr
|
||||
style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;" />
|
||||
|
||||
<div id="demo1" class="row carousel slide" data-ride="carousel">
|
||||
<!-- The slideshow -->
|
||||
<div class="carousel-inner">
|
||||
<div class="carousel-item active" style="min-height:0px">
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/14.0/export_stockinfo_xls/" target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-top-left-radius:10px; border-top-right-radius:10px"
|
||||
src="./assets/modules/export_image.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/14.0/dashboard_pos/" target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-top-left-radius:10px; border-top-right-radius:10px"
|
||||
src="./assets/modules/pos_image.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/14.0/product_approval_management/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-top-left-radius:10px; border-top-right-radius:10px"
|
||||
src="./assets/modules/approval_image.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="carousel-item" style="min-height:0px">
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/14.0/base_account_budget/" target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-top-left-radius:10px; border-top-right-radius:10px"
|
||||
src="./assets/modules/budget_image.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/14.0/shopify_odoo_connector/" target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-top-left-radius:10px; border-top-right-radius:10px"
|
||||
src="./assets/modules/shopify_image.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/14.0/odoo11_magento2/" target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-top-left-radius:10px; border-top-right-radius:10px"
|
||||
src="./assets/modules/magento_image.png">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Left and right controls -->
|
||||
<a class="carousel-control-prev" href="#demo1" data-slide="prev"
|
||||
style="left:-25px;width: 35px;color: #000;"> <span class="carousel-control-prev-icon"><i
|
||||
class="fa fa-chevron-left" style="font-size:24px"></i></span> </a> <a
|
||||
class="carousel-control-next" href="#demo1" data-slide="next"
|
||||
style="right:-25px;width: 35px;color: #000;">
|
||||
<span class="carousel-control-next-icon"><i class="fa fa-chevron-right"
|
||||
style="font-size:24px"></i></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF SUGGESTED PRODUCTS -->
|
||||
|
||||
<!-- OUR SERVICES -->
|
||||
<section class="container" style="margin-top: 6rem !important;">
|
||||
<div class="row">
|
||||
<div class="col-lg-12 d-flex flex-column justify-content-center align-items-center">
|
||||
<h2 style="color: #212529 !important;">Our Services</h2>
|
||||
<hr
|
||||
style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;" />
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #1dd1a1 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/cogs.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Customization</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #ff6b6b !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/wrench.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Implementation</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #6462CD !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/lifebuoy.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Support</h6>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #ffa801 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/user.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Hire
|
||||
Odoo
|
||||
Developer</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #54a0ff !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/puzzle.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Integration</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #6d7680 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/update.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Migration</h6>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #786fa6 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/consultation.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Consultancy</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #f8a5c2 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/training.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Implementation</h6>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="background-color: #e6be26 !important; border-radius: 15px !important; height: 80px; width: 80px;">
|
||||
<img src="assets/icons/license.png" class="img-responsive" height="48px" width="48px">
|
||||
</div>
|
||||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
|
||||
Odoo
|
||||
Licensing Consultancy</h6>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- END OF END OF OUR SERVICES -->
|
||||
|
||||
<!-- OUR INDUSTRIES -->
|
||||
<section class="container" style="margin-top: 6rem !important;">
|
||||
<div class="row">
|
||||
<div class="col-lg-12 d-flex flex-column justify-content-center align-items-center">
|
||||
<h2 style="color: #212529 !important;">Our Industries</h2>
|
||||
<hr
|
||||
style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;" />
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="./assets/icons/trading-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5
|
||||
style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Trading
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Easily procure
|
||||
and
|
||||
sell your products</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="./assets/icons/pos-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5
|
||||
style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
POS
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Easy
|
||||
configuration
|
||||
and convivial experience</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="./assets/icons/education-black.png" class="img-responsive mb-3" height="48px"
|
||||
width="48px">
|
||||
<h5
|
||||
style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Education
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
A platform for
|
||||
educational management</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="./assets/icons/manufacturing-black.png" class="img-responsive mb-3" height="48px"
|
||||
width="48px">
|
||||
<h5
|
||||
style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Manufacturing
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Plan, track and
|
||||
schedule your operations</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="./assets/icons/ecom-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5
|
||||
style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
E-commerce & Website
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Mobile
|
||||
friendly,
|
||||
awe-inspiring product pages</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="./assets/icons/service-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5
|
||||
style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Service Management
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Keep track of
|
||||
services and invoice</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="./assets/icons/restaurant-black.png" class="img-responsive mb-3" height="48px"
|
||||
width="48px">
|
||||
<h5
|
||||
style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Restaurant
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
Run your bar or
|
||||
restaurant methodically</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3">
|
||||
<div class="my-4 d-flex flex-column justify-content-center"
|
||||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;">
|
||||
<img src="./assets/icons/hotel-black.png" class="img-responsive mb-3" height="48px" width="48px">
|
||||
<h5
|
||||
style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
|
||||
Hotel Management
|
||||
</h5>
|
||||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
|
||||
An
|
||||
all-inclusive
|
||||
hotel management application</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- END OF END OF OUR INDUSTRIES -->
|
||||
|
||||
<!-- FOOTER -->
|
||||
<!-- Footer Section -->
|
||||
<section class="container" style="margin: 5rem auto 2rem;">
|
||||
<div class="row" style="max-width:1540px;">
|
||||
<div class="col-lg-12 d-flex flex-column justify-content-center align-items-center">
|
||||
<h2 style="color: #212529 !important;">Need Help?</h2>
|
||||
<hr
|
||||
style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Contact Cards -->
|
||||
<div class="row d-flex justify-content-center align-items-center"
|
||||
style="max-width:1540px; margin: 0 auto 2rem auto;">
|
||||
|
||||
<div class="col-lg-12" style="padding: 0rem 3rem 2rem; border-radius: 10px; margin-right: 3rem; ">
|
||||
|
||||
<div class="row mt-4">
|
||||
<div class="col-lg-6">
|
||||
<a href="mailto:odoo@cybrosys.com" target="_blank" class="btn btn-block mb-2 deep_hover"
|
||||
style="text-decoration: none; background-color: #4d4d4d; color: #FFF; border-radius: 4px;"><i
|
||||
class="fa fa-envelope mr-2"></i>odoo@cybrosys.com</a>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<a href="https://api.whatsapp.com/send?phone=918606827707" target="_blank"
|
||||
class="btn btn-block mb-2 deep_hover"
|
||||
style="text-decoration: none; background-color: #25D366; color: #FFF; border-radius: 4px;"><i
|
||||
class="fa fa-whatsapp mr-2"></i>WhatsApp</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- End of Contact Cards -->
|
||||
</section>
|
||||
<!-- Footer -->
|
||||
<section class="oe_container" style="padding: 2rem 3rem 1rem;">
|
||||
<div class="row" style="max-width:1540px; margin: 0 auto; margin-right: 3rem; ">
|
||||
<!-- Logo -->
|
||||
<div class="col-lg-12 d-flex justify-content-center align-items-center" style="margin-top: 3rem;">
|
||||
<img src="https://www.cybrosys.com/images/logo.png" width="200px" height="auto" />
|
||||
</div>
|
||||
<!-- End of Logo -->
|
||||
<div class="col-lg-12">
|
||||
<hr
|
||||
style="margin-top: 3rem;background: linear-gradient(90deg, rgba(2,0,36,0) 0%, rgba(229,229,229,1) 33%, rgba(229,229,229,1) 58%, rgba(0,212,255,0) 100%); height: 2px; border-style: none;">
|
||||
<!-- End of Footer Section -->
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- END OF FOOTER -->
|
||||
|
||||
</div>
|
|
@ -0,0 +1,34 @@
|
|||
.cb_sticky {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index : 10;
|
||||
}
|
||||
|
||||
.cb_sticky tr th{
|
||||
outline: 1px solid #dee2e6;
|
||||
border: none;
|
||||
outline-offset: -1px;
|
||||
left: 0;
|
||||
position: sticky !important;
|
||||
}
|
||||
|
||||
.cb_sticky_first_child{
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
tbody .o_pivot_header_cell_opened {
|
||||
position: sticky;
|
||||
left : 0;
|
||||
outline: 1px solid #dee2e6;
|
||||
}
|
||||
|
||||
tbody .o_pivot_header_cell_closed {
|
||||
position: sticky;
|
||||
left : 0;
|
||||
outline: 1px solid #dee2e6;
|
||||
}
|
||||
|
||||
tbody .dropdown > .dropdown-menu.o_pivot_field_menu.show {
|
||||
left : 104%;
|
||||
margin: -20px 0px 0px 0px;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<templates>
|
||||
|
||||
<t t-name="PivotRenderer" t-inherit="web.PivotRenderer" t-inherit-mode="extension" owl="1">
|
||||
<xpath expr="//thead" position="attributes">
|
||||
<attribute name="class">cb_sticky</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//thead/tr/t/th[contains(@t-att-colspan, 'cell.width')]" position="attributes">
|
||||
<attribute name="class">cb_sticky_first_child</attribute>
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
</templates>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<template id="assets_backend" name="pivot_sticky_header" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" type="text/css" href="/sticky_pivot_view/static/src/css/main.css"/>
|
||||
</xpath>
|
||||
</template>
|
||||
</odoo>
|