Initial commit: Vertical Industry packages

This commit is contained in:
Ernad Husremovic 2025-08-29 15:20:52 +02:00
commit d5567a0017
766 changed files with 733028 additions and 0 deletions

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo><data>
<record id="badge_user_kanban_view" model="ir.ui.view" >
<field name="name">Badge User Kanban View</field>
<field name="model">gamification.badge.user</field>
<field name="arch" type="xml">
<kanban class="oe_background_grey" action="action_open_badge" type="object">
<field name="badge_name"/>
<field name="badge_id"/>
<field name="user_id"/>
<field name="comment"/>
<field name="create_date"/>
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_card oe_kanban_global_click oe_kanban_badge oe_kanban_color_white o_kanban_gamification">
<div class="o_kanban_content">
<div class="o_kanban_image">
<a type="open"><img t-att-src="kanban_image('gamification.badge', 'image_1024', record.badge_id.raw_value)" t-att-title="record.badge_name.value" t-att-alt="record.badge_name.value" /></a>
</div>
<div class="oe_kanban_details">
<h4 class="mt0 mb0">
<a class="o_kanban_record_title" type="open"><t t-esc="record.badge_name.raw_value" /></a>
</h4>
<t t-if="record.comment.raw_value">
<p class="o_kanban_record_subtitle"><em><field name="comment"/></em></p>
</t>
<p>Granted by <a type="open"><field name="create_uid" /></a> the <t t-esc="luxon.DateTime.fromISO(record.create_date.raw_value).toFormat('D')" /></p>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
</data></odoo>

View file

@ -0,0 +1,166 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Badge views -->
<record id="gamification_badge_view_search" model="ir.ui.view">
<field name="name">gamification.badge.view.search</field>
<field name="model">gamification.badge</field>
<field name="arch" type="xml">
<search string="Search Badge">
<field name="name"/>
<separator/>
<filter string="Archived" name="inactive" domain="[('active', '=', False)]"/>
</search>
</field>
</record>
<record id="badge_list_action" model="ir.actions.act_window">
<field name="name">Badges</field>
<field name="res_model">gamification.badge</field>
<field name="view_mode">kanban,tree,form</field>
<field name="search_view_id" ref="gamification_badge_view_search"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new badge
</p><p>
A badge is a symbolic token granted to a user as a sign of reward.
It can be deserved automatically when some conditions are met or manually by users.
Some badges are harder than others to get with specific conditions.
</p>
</field>
</record>
<record id="badge_list_view" model="ir.ui.view">
<field name="name">Badge List</field>
<field name="model">gamification.badge</field>
<field name="arch" type="xml">
<tree string="Badge List">
<field name="name"/>
<field name="granted_count"/>
<field name="stat_this_month"/>
<field name="stat_my"/>
<field name="rule_auth"/>
</tree>
</field>
</record>
<record id="badge_form_view" model="ir.ui.view">
<field name="name">Badge Form</field>
<field name="model">gamification.badge</field>
<field name="arch" type="xml">
<form string="Badge">
<header>
<button string="Grant this Badge" type="action" name="%(action_grant_wizard)d" class="oe_highlight" attrs="{'invisible': [('remaining_sending','=',0)]}" />
</header>
<sheet>
<div class="oe_button_box" name="button_box"/>
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
<field name="image_1920" widget="image" class="oe_avatar" options="{'preview_image': 'image_128'}"/>
<div class="oe_title">
<label for="name"/>
<h1>
<field name="name" placeholder="e.g. Problem Solver"/>
</h1>
</div>
<group>
<field name="description" nolabel="1" placeholder="Badge Description" colspan="2"/>
</group>
<group string="Granting">
<div class="oe_grey" colspan="2">
Security rules to define who is allowed to manually grant badges. Not enforced for administrator.
</div>
<group>
<field name="active" invisible="1"/>
<field name="rule_auth" widget="radio"/>
<field name="rule_auth_user_ids" attrs="{'invisible': [('rule_auth','!=','users')]}" widget="many2many_tags" />
<field name="rule_auth_badge_ids" attrs="{'invisible': [('rule_auth','!=','having')]}" widget="many2many_tags" />
<field name="rule_max" attrs="{'invisible': [('rule_auth','=','nobody')]}" />
<field name="rule_max_number" attrs="{'invisible': ['|',('rule_max','=',False),('rule_auth','=','nobody')]}"/>
<label for="stat_my_monthly_sending"/>
<div>
<field name="stat_my_monthly_sending" attrs="{'invisible': [('rule_auth','=','nobody')]}" />
<div attrs="{'invisible': [('remaining_sending','=',-1)]}" class="oe_grey">
You can still grant <field name="remaining_sending" class="oe_inline"/> badges this month
</div>
<div attrs="{'invisible': [('remaining_sending','!=',-1)]}" class="oe_grey">
No monthly sending limit
</div>
</div>
</group>
</group>
<group string="Rewards for challenges">
<field name="challenge_ids" mode="kanban" widget="many2many" nolabel="1" context="{'default_reward_id': active_id}" colspan="2"/>
<field name="level" colspan="2"/>
</group>
<group id="badge_statistics" string="Statistics">
<group>
<field name="granted_count"/>
<field name="stat_this_month"/>
<field name="granted_users_count"/>
</group>
<group>
<field name="stat_my"/>
<field name="stat_my_this_month"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="badge_kanban_view" model="ir.ui.view" >
<field name="name">Badge Kanban View</field>
<field name="model">gamification.badge</field>
<field name="arch" type="xml">
<kanban class="o_kanban_badge">
<field name="id"/>
<field name="name"/>
<field name="description"/>
<field name="stat_my"/>
<field name="granted_count"/>
<field name="stat_this_month"/>
<field name="unique_owner_ids"/>
<field name="stat_my_monthly_sending"/>
<field name="remaining_sending" />
<field name="rule_max_number" />
<templates>
<t t-name="kanban-box">
<div t-attf-class="o_kanban_gamification oe_kanban_global_click #{record.stat_my.raw_value ? 'oe_kanban_color_5' : 'oe_kanban_color_white'}">
<div class="o_kanban_image">
<img t-att-src="kanban_image('gamification.badge', 'image_1024', record.id.raw_value)" t-att-title="record.name.value" t-att-alt="record.name.value"/>
</div>
<div class="oe_kanban_details">
<strong class="o_kanban_record_title"><field name="name"/></strong>
<span class="oe_grey">
<t t-if="record.remaining_sending.value != -1">
<t t-esc="record.stat_my_monthly_sending.value"/>/<t t-esc="record.rule_max_number.value"/>
</t>
<t t-if="record.remaining_sending.value == -1">
<t t-esc="record.stat_my_monthly_sending.value"/>/∞
</t>
</span>
<div t-if="record.remaining_sending.value == 0" class="oe_grey">Can not grant</div>
<div>
<strong><t t-esc="record.granted_count.raw_value"/></strong> granted,
<strong><t t-esc="record.stat_this_month.raw_value"/></strong> this month
</div>
<div t-if="!widget.isHtmlEmpty(record.description.value)" class="o_kanban_badge_description pb-3">
<em t-out="record.description.value"/>
<div>
<t t-foreach="record.unique_owner_ids.raw_value.slice(0,11)" t-as="owner" t-key="owner">
<img class="oe_kanban_avatar o_image_24_cover rounded-circle" t-att-src="kanban_image('res.users', 'avatar_128', owner)" t-att-data-member_id="owner" alt="Owner"/>
</t>
</div>
</div>
<div t-if="record.remaining_sending.value != 0 and !selection_mode" class="o_kanban_button">
<button type="action" name="%(action_grant_wizard)d" class="oe_highlight btn btn-primary">Grant</button>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
</odoo>

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo><data>
<record id="challenge_line_list_view" model="ir.ui.view">
<field name="name">Challenge line list</field>
<field name="model">gamification.challenge.line</field>
<field name="arch" type="xml">
<tree string="Challenge Lines" >
<field name="definition_id"/>
<field name="target_goal" string="Target"/>
</tree>
</field>
</record>
</data></odoo>

View file

@ -0,0 +1,206 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="challenge_list_view" model="ir.ui.view">
<field name="name">Challenges List</field>
<field name="model">gamification.challenge</field>
<field name="arch" type="xml">
<tree string="Challenges" decoration-info="state == 'draft'" decoration-muted="state == 'done'">
<field name="name"/>
<field name="period"/>
<field name="manager_id"/>
<field name="state"/>
</tree>
</field>
</record>
<record id="challenge_form_view" model="ir.ui.view">
<field name="name">Challenge Form</field>
<field name="model">gamification.challenge</field>
<field name="arch" type="xml">
<form string="Challenge">
<header>
<button string="Start Challenge" type="object" name="action_start" states="draft" class="oe_highlight"/>
<button string="Refresh Challenge" type="object" name="action_check" states="inprogress"/>
<button string="Send Report" type="object" name="action_report_progress" states="inprogress,done" groups="base.group_no_one"/>
<field name="state" widget="statusbar" options="{'clickable': '1'}"/>
</header>
<sheet>
<!-- action buttons -->
<div class="oe_button_box" name="button_box">
<button type="object"
name="action_view_users"
class="oe_stat_button"
icon="fa-users">
<field name="user_count" string="Participants" widget="statinfo"/>
</button>
<button type="action"
name="%(goals_from_challenge_act)d"
class="oe_stat_button"
icon="fa-gift"
attrs="{'invisible': [('state','=','draft')]}">
<div class="o_field_widget o_stat_info">
<span class="o_stat_text">Related</span>
<span class="o_stat_text">Goals</span>
</div>
</button>
</div>
<div class="oe_title">
<label for="name"/>
<h1>
<field name="name" placeholder="e.g. Monthly Sales Objectives"/>
</h1>
<label for="user_domain" string="Assign Challenge to"/>
<div>
<field name="user_domain" widget="domain" options="{'model': 'res.users'}" />
</div>
</div>
<group>
<group>
<field name="period" attrs="{'readonly':[('state','!=','draft')]}"/>
<field name="visibility_mode" widget="radio" colspan="1" />
</group>
<group>
<field name="manager_id"/>
<field name="start_date" attrs="{'readonly':[('state','!=','draft')]}"/>
<field name="end_date" attrs="{'readonly':[('state','!=','draft')]}"/>
</group>
</group>
<notebook>
<page string="Goals" name="goals">
<field name="line_ids" nolabel="1" colspan="4">
<tree string="Line List" editable="bottom" >
<field name="sequence" widget="handle"/>
<field name="definition_id" />
<field name="condition"/>
<field name="target_goal" string="Target"/>
<field name="definition_full_suffix"/>
</tree>
</field>
<field name="description" placeholder="Describe the challenge: what is does, who it targets, why it matters..."/>
</page>
<page string="Reward" name="reward">
<group>
<field name="reward_id" attrs="{'required': [('reward_realtime','=', True)]}" />
<field name="reward_first_id" />
<field name="reward_second_id" attrs="{'invisible': [('reward_first_id','=', False)]}" />
<field name="reward_third_id" attrs="{'invisible': ['|',('reward_first_id','=', False),('reward_second_id','=', False)]}" />
<field name="reward_failure" attrs="{'invisible': [('reward_first_id','=', False)]}" />
<field name="reward_realtime" />
</group>
<div class="oe_grey">
<p>Badges are granted when a challenge is finished. This is either at the end of a running period (eg: end of the month for a monthly challenge), at the end date of a challenge (if no periodicity is set) or when the challenge is manually closed.</p>
</div>
</page>
<page string="Advanced Options" name="advanced_options">
<group string="Subscriptions">
<field name="invited_user_ids" widget="many2many_tags" />
</group>
<group string="Notification Messages">
<div class="oe_grey" colspan="4">
<p>Depending on the Display mode, reports will be individual or shared.</p>
</div>
<group colspan="4">
<field name="report_message_frequency"/>
<field name="report_template_id" attrs="{'invisible': [('report_message_frequency','=','never')]}" />
<field name="report_message_group_id" attrs="{'invisible': [('report_message_frequency','=','never')]}" />
</group>
</group>
<group string="Reminders for Manual Goals">
<label for="remind_update_delay" />
<div>
<field name="remind_update_delay" class="oe_inline"/> days
</div>
</group>
<group string="Category" groups="base.group_no_one">
<field name="challenge_category" widget="radio" />
</group>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids"/>
<field name="message_ids"/>
</div>
</form>
</field>
</record>
<record model="ir.ui.view" id="view_challenge_kanban">
<field name="name">Challenge Kanban</field>
<field name="model">gamification.challenge</field>
<field name="arch" type="xml">
<kanban string="Challenges" class="oe_background_grey">
<field name="line_ids"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_card o_kanban_gamification oe_kanban_global_click">
<div class="o_kanban_content">
<strong>
<h4 class="o_kanban_record_title"><field name="name"/></h4>
<div class="o_kanban_record_subtitle">
<a type="action" name="%(goals_from_challenge_act)d"
style="margin-right: 10px" tabindex="-1">
<span><t t-esc="record.line_ids.raw_value.length"/> Goals</span>
</a><br />
<a type="object" name="action_view_users"
style="margin-right: 10px" tabindex="-1">
<span><field name="user_count"/> Participants</span>
</a>
</div>
</strong>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="challenge_list_action" model="ir.actions.act_window">
<field name="name">Challenges</field>
<field name="res_model">gamification.challenge</field>
<field name="view_mode">kanban,tree</field>
<field name="context">{'search_default_inprogress':True, 'default_inprogress':True}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new challenge
</p><p>
Assign a list of goals to chosen users to evaluate them.
The challenge can use a period (weekly, monthly...) for automatic creation of goals.
The goals are created for the specified users or member of the group.
</p>
</field>
</record>
<!-- Specify form view ID to avoid selecting view_challenge_wizard -->
<record id="challenge_list_action_view1" model="ir.actions.act_window.view">
<field eval="1" name="sequence"/>
<field name="view_mode">kanban</field>
<field name="act_window_id" ref="challenge_list_action"/>
<field name="view_id" ref="view_challenge_kanban"/>
</record>
<record id="challenge_list_action_view2" model="ir.actions.act_window.view">
<field eval="10" name="sequence"/>
<field name="view_mode">form</field>
<field name="act_window_id" ref="challenge_list_action"/>
<field name="view_id" ref="challenge_form_view"/>
</record>
<record id="challenge_search_view" model="ir.ui.view">
<field name="name">Challenge Search</field>
<field name="model">gamification.challenge</field>
<field name="arch" type="xml">
<search string="Search Challenges">
<filter name="inprogress" string="Running Challenges"
domain="[('state', '=', 'inprogress')]"/>
<filter name="hr_challenges" string="HR Challenges"
domain="[('challenge_category', '=', 'hr')]"/>
<field name="name"/>
<group expand="0" string="Group By">
<filter string="State" name="state" domain="[]" context="{'group_by':'state'}"/>
<filter string="Period" name="period" domain="[]" context="{'group_by':'period'}"/>
</group>
</search>
</field>
</record>
</odoo>

View file

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="goal_definition_list_action" model="ir.actions.act_window">
<field name="name">Goal Definitions</field>
<field name="res_model">gamification.goal.definition</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new goal definition
</p><p>
A goal definition is a technical specification of a condition to reach.
The dates, values to reach or users are defined in goal instance.
</p>
</field>
</record>
<record id="goal_definition_list_view" model="ir.ui.view">
<field name="name">Goal Definitions List</field>
<field name="model">gamification.goal.definition</field>
<field name="arch" type="xml">
<tree string="Goal Definitions">
<field name="name"/>
<field name="computation_mode"/>
</tree>
</field>
</record>
<record id="goal_definition_form_view" model="ir.ui.view">
<field name="name">Goal Definitions Form</field>
<field name="model">gamification.goal.definition</field>
<field name="arch" type="xml">
<form string="Goal definitions">
<sheet>
<label for="name"/>
<h1>
<field name="name" placeholder="e.g. Get started" class="w-100"/>
</h1>
<label for="description"/>
<div>
<field name="description" placeholder="e.g. Register to the platform" class="w-100"/>
</div>
<group string="How is the goal computed?" name="compute_details">
<field widget="radio" name="computation_mode"/>
<!-- Hide the fields below if manually -->
<field name="model_id" class="oe_inline"
attrs="{'invisible':[('computation_mode','not in',('sum', 'count'))], 'required':[('computation_mode','in',('sum', 'count'))]}"/>
<field name="model_inherited_ids" invisible="1"/>
<field name="field_id" class="oe_inline" options="{'no_create': True}"
attrs="{'invisible':[('computation_mode','!=','sum')], 'required':[('computation_mode','=','sum')]}"/>
<field name="field_date_id" class="oe_inline" attrs="{'invisible':[('computation_mode','not in',('sum', 'count'))]}"/>
<field name="domain" attrs="{'invisible':[('computation_mode','not in',('sum', 'count'))], 'required':[('computation_mode','in',('sum', 'count'))]}" class="oe_inline"/>
<field name="compute_code" attrs="{'invisible':[('computation_mode','!=','python')], 'required':[('computation_mode','=','python')]}"/>
<field name="condition" widget="radio"/>
</group>
<group string="Optimisation" name="optimisation" attrs="{'invisible': [('computation_mode', 'not in', ('sum', 'count'))]}">
<field name="batch_mode" />
<div colspan="2">In batch mode, the domain is evaluated globally. If enabled, do not use keyword 'user' in above filter domain.</div>
<field name="batch_distinctive_field" attrs="{'invisible': [('batch_mode', '=', False)], 'required': [('batch_mode', '=', True)]}"
domain="[('model_id', '=', model_id)]" class="oe_inline" />
<field name="batch_user_expression" attrs="{'invisible': [('batch_mode', '=', False)], 'required': [('batch_mode', '=', True)]}" class="oe_inline"
placeholder="e.g. user.partner_id.id"/>
</group>
<group string="Formatting Options" name="format_options">
<field name="display_mode" widget="radio" />
<field name="suffix" placeholder="e.g. days" class="oe_inline"/>
<field name="monetary"/>
</group>
<group string="Clickable Goals" name="clickable_goals" attrs="{'invisible': [('computation_mode', '=', 'manually')]}">
<field name="action_id" class="oe_inline"/>
<field name="res_id_field" attrs="{'invisible': [('action_id', '=', False)]}" class="oe_inline"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="goal_definition_search_view" model="ir.ui.view">
<field name="name">Goal Definition Search</field>
<field name="model">gamification.goal.definition</field>
<field name="arch" type="xml">
<search string="Search Goal Definitions">
<field name="name"/>
<field name="model_id"/>
<field name="field_id"/>
<group expand="0" string="Group By">
<filter string="Model" name="model" domain="[]" context="{'group_by':'model_id'}"/>
<filter string="Computation Mode" name="computationmode" domain="[]" context="{'group_by':'computation_mode'}"/>
</group>
</search>
</field>
</record>
</odoo>

View file

@ -0,0 +1,210 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Goal views -->
<record id="goal_list_action" model="ir.actions.act_window">
<field name="name">Goals</field>
<field name="res_model">gamification.goal</field>
<field name="view_mode">tree,form,kanban</field>
<field name="context">{'search_default_group_by_user': True, 'search_default_group_by_definition': True}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new goal
</p><p>
A goal is defined by a user and a goal definition.
Goals can be created automatically by using challenges.
</p>
</field>
</record>
<record id="goals_from_challenge_act" model="ir.actions.act_window">
<field name="res_model">gamification.goal</field>
<field name="name">Related Goals</field>
<field name="view_mode">kanban,tree,form</field>
<field name="context">{'search_default_group_by_definition': True, 'search_default_inprogress': True, 'search_default_challenge_id': active_id, 'default_challenge_id': active_id}</field>
<field name="help" type="html">
<p class="o_view_nocontent_empty_folder">
No goal found
</p><p>
There is no goal associated to this challenge matching your search.
Make sure that your challenge is active and assigned to at least one user.
</p>
</field>
</record>
<record id="goal_list_view" model="ir.ui.view">
<field name="name">Goal List</field>
<field name="model">gamification.goal</field>
<field name="arch" type="xml">
<tree string="Goal List" decoration-danger="state == 'failed'" decoration-success="state == 'reached'" decoration-muted="state == 'canceled'" create="false">
<field name="definition_id" invisible="1" />
<field name="user_id" invisible="1" />
<field name="start_date"/>
<field name="end_date"/>
<field name="current"/>
<field name="target_goal"/>
<field name="completeness" widget="progressbar"/>
<field name="state" invisible="1"/>
<field name="line_id" invisible="1"/>
</tree>
</field>
</record>
<record id="goal_form_view" model="ir.ui.view">
<field name="name">Goal Form</field>
<field name="model">gamification.goal</field>
<field name="arch" type="xml">
<form string="Goal" create="false">
<header>
<button string="Start goal" type="object" name="action_start" states="draft" class="oe_highlight"/>
<button string="Goal Reached" type="object" name="action_reach" states="inprogress" />
<button string="Goal Failed" type="object" name="action_fail" states="inprogress"/>
<button string="Reset Completion" type="object" name="action_cancel" states="failed,reached" groups="base.group_no_one" />
<field name="state" widget="statusbar" statusbar_visible="draft,inprogress,reached" />
</header>
<sheet>
<group>
<group string="Reference">
<field name="definition_id" attrs="{'readonly':[('state','!=','draft')]}"/>
<field name="user_id" attrs="{'readonly':[('state','!=','draft')]}"/>
<field name="challenge_id" />
</group>
<group string="Schedule">
<field name="start_date" attrs="{'readonly':[('state','!=','draft')]}"/>
<field name="end_date" />
<field name="computation_mode" invisible="1"/>
<label for="remind_update_delay" attrs="{'invisible':[('computation_mode','!=', 'manually')]}"/>
<div attrs="{'invisible':[('computation_mode','!=', 'manually')]}">
<field name="remind_update_delay" class="oe_inline"/>
days
</div>
<field name="last_update" groups="base.group_no_one"/>
</group>
<group string="Data" colspan="4">
<label for="target_goal" />
<div>
<field name="target_goal" attrs="{'readonly':[('state','!=','draft')]}" class="oe_inline"/>
<field name="definition_suffix" class="oe_inline"/>
</div>
<label for="current" />
<div>
<field name="current" class="oe_inline"/>
<button string="refresh" type="object" name="update_goal" class="oe_link" attrs="{'invisible':['|',('computation_mode', '=', 'manually'),('state', '=', 'draft')]}" />
<div class="oe_grey" attrs="{'invisible':[('definition_id', '=', False)]}">
Reached when current value is <strong><field name="definition_condition" class="oe_inline"/></strong> than the target.
</div>
</div>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="goal_search_view" model="ir.ui.view">
<field name="name">Goal Search</field>
<field name="model">gamification.goal</field>
<field name="arch" type="xml">
<search string="Search Goals">
<filter name="my" string="My Goals" domain="[('user_id', '=', uid)]"/>
<separator/>
<filter name="draft" string="Draft" domain="[('state', '=', 'draft')]"/>
<filter name="inprogress" string="Running"
domain="[
'|',
('state', '=', 'inprogress'),
'&amp;',
('state', 'in', ('done', 'failed')),
('end_date', '>=', context_today().strftime('%Y-%m-%d'))
]"/>
<filter name="closed" string="Done"
domain="[
('state', 'in', ('reached', 'failed')),
'|',
('end_date', '=', False),
('end_date', '&lt;', context_today().strftime('%Y-%m-%d'))
]"/>
<separator/>
<field name="user_id"/>
<field name="definition_id"/>
<field name="challenge_id"/>
<group expand="0" string="Group By">
<filter name="group_by_user" string="User" domain="[]" context="{'group_by':'user_id'}"/>
<filter name="group_by_definition" string="Goal Definition" domain="[]" context="{'group_by':'definition_id'}"/>
<filter string="State" name="state" domain="[]" context="{'group_by':'state'}"/>
<filter string="End Date" name="enddate" domain="[]" context="{'group_by':'end_date'}"/>
</group>
</search>
</field>
</record>
<record id="goal_kanban_view" model="ir.ui.view" >
<field name="name">Goal Kanban View</field>
<field name="model">gamification.goal</field>
<field name="arch" type="xml">
<kanban class="oe_background_grey" create="false">
<field name="definition_id"/>
<field name="user_id"/>
<field name="current"/>
<field name="completeness"/>
<field name="state"/>
<field name="target_goal"/>
<field name="definition_description"/>
<field name="definition_condition"/>
<field name="definition_suffix"/>
<field name="definition_display"/>
<field name="start_date"/>
<field name="end_date"/>
<field name="last_update"/>
<templates>
<t t-name="kanban-tooltip">
<ul class="oe_kanban_tooltip">
<li><t t-esc="record.definition_description.value" /></li>
</ul>
</t>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_card oe_kanban_global_click o_kanban_gamification #{record.end_date.raw_value &lt; record.last_update.raw_value and record.state.raw_value == 'failed' ? 'oe_kanban_color_2' : ''} #{record.end_date.raw_value &lt; record.last_update.raw_value and record.state.raw_value == 'reached' ? 'oe_kanban_color_5' : ''}">
<div class="o_kanban_content text-center">
<p><strong><h4 class="oe_goal_name" tooltip="kanban-tooltip"><field name="definition_id" /></h4></strong></p>
<img class="o_image_24_cover me-1 rounded-circle" t-att-src="kanban_image('res.users', 'avatar_128', record.user_id.raw_value)" t-att-title="record.user_id.value" t-att-alt="record.user_id.value"/>
<field name="user_id" class="fw-bold"/>
<div class="o_goal_state_block pt-3 fs-1 fw-bolder">
<t t-if="record.definition_display.raw_value == 'boolean'">
<div class="o_goal_state">
<t t-if="record.state.raw_value=='reached'"><i role="img" class="text-success fa fa-check fa-3x" title="Goal Reached" aria-label="Goal Reached"/></t>
<t t-if="record.state.raw_value=='inprogress'"><i role="img" class="fa fa-clock-o fa-3x" title="Goal in Progress" aria-label="Goal in Progress"/></t>
<t t-if="record.state.raw_value=='failed'"><i role="img" class="text-danger fa fa-times fa-3x" title="Goal Failed" aria-label="Goal Failed"/></t>
</div>
</t>
<t t-if="record.definition_display.raw_value == 'progress'">
<t t-if="record.definition_condition.raw_value =='higher'">
<field name="current" widget="gauge" options="{'max_field': 'target_goal', 'label_field': 'definition_suffix', 'style': 'width:160px; height: 120px;'}" />
</t>
<t t-if="record.definition_condition.raw_value != 'higher'">
<div t-attf-class="o_goal_state #{record.current.raw_value == record.target_goal.raw_value+1 ? 'text-warning' : record.current.raw_value &gt; record.target_goal.raw_value ? 'text-danger' : 'text-success'}">
<t t-esc="record.current.raw_value" />
</div>
<em>Target: less than <t t-esc="record.target_goal.raw_value" /></em>
</t>
</t>
</div>
<p>
<t t-if="record.start_date.value">
From <t t-esc="record.start_date.value" />
</t>
<t t-if="record.end_date.value">
To <t t-esc="record.end_date.value" />
</t>
</p>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
</odoo>

View file

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!-- Ranks views -->
<record id="gamification_karma_ranks_action" model="ir.actions.act_window">
<field name="name">Ranks</field>
<field name="res_model">gamification.karma.rank</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new rank
</p><p>
A rank correspond to a fixed karma level. The more you have karma, the more your rank is high.
This is used to quickly know which user is new or old or highly or not active.
</p>
</field>
</record>
<record id="gamification_karma_ranks_view_search" model="ir.ui.view">
<field name="name">gamification.karma.ranks.view.search</field>
<field name="model">gamification.karma.rank</field>
<field name="arch" type="xml">
<search string="Search Ranks">
<field name="name"/>
<field name="karma_min"/>
<field name="description"/>
<field name="user_ids"/>
</search>
</field>
</record>
<record id="gamification_karma_ranks_view_tree" model="ir.ui.view">
<field name="name">gamification.karma.ranks.view.tree</field>
<field name="model">gamification.karma.rank</field>
<field name="arch" type="xml">
<tree string="Ranks List">
<field name="name"/>
<field name="karma_min"/>
<field name="rank_users_count"/>
</tree>
</field>
</record>
<record id="gamification_karma_rank_view_form" model="ir.ui.view">
<field name="name">gamification.karma.rank.view.form</field>
<field name="model">gamification.karma.rank</field>
<field name="arch" type="xml">
<form string="Rank">
<sheet>
<div class="oe_button_box" name="button_box">
<button type="action" class="oe_stat_button" icon="fa-users" name="%(action_current_rank_users)d">
<div class="o_form_field o_stat_info">
<span class="o_stat_value">
<field name="rank_users_count" />
</span>
<span class="o_stat_text">Users</span>
</div>
</button>
</div>
<field name="image_1920" widget="image" class="oe_avatar" options="{'preview_image': 'image_128'}"/>
<div class="oe_title">
<label for="name"/>
<h1>
<field name="name" placeholder="e.g. Master Chief"/>
</h1>
</div>
<group>
<field name="karma_min"/>
<field name="create_date" invisible="1"/>
</group>
<notebook>
<page string="Description" name="description">
<field name="description" placeholder="e.g. A Master Chief knows quite everything on the forum! You cannot beat him!"/>
</page>
<page string="Motivational" name="motivational">
<field name="description_motivational" placeholder="e.g. Reach this rank to gain a free mug !"/>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
</data>
</odoo>

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo><data>
<record id="gamification_karma_tracking_view_search" model="ir.ui.view">
<field name="name">gamification.karma.tracking.view.search</field>
<field name="model">gamification.karma.tracking</field>
<field name="arch" type="xml">
<search string="Search Trackings">
<field name="user_id"/>
<field name="tracking_date"/>
<filter string="Consolidated" name="filter_consolidated"
domain="[('consolidated', '=', True)]"/>
<group string="Group By" expand="1">
<filter string="User" name="group_by_user_id"
context="{'group_by': 'user_id'}"/>
</group>
</search>
</field>
</record>
<record id="gamification_karma_tracking_view_tree" model="ir.ui.view">
<field name="name">gamification.karma.tracking.view.tree</field>
<field name="model">gamification.karma.tracking</field>
<field name="arch" type="xml">
<tree string="Trackings">
<field name="user_id"/>
<field name="tracking_date"/>
<field name="old_value"/>
<field name="new_value"/>
<field name="consolidated"/>
</tree>
</field>
</record>
<record id="gamification_karma_tracking_view_form" model="ir.ui.view">
<field name="name">gamification.karma.tracking.view.form</field>
<field name="model">gamification.karma.tracking</field>
<field name="arch" type="xml">
<form string="Tracking">
<sheet>
<group>
<field name="user_id"/>
<field name="tracking_date"/>
<field name="old_value"/>
<field name="new_value"/>
<field name="consolidated"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="gamification_karma_tracking_action" model="ir.actions.act_window">
<field name="name">Trackings</field>
<field name="res_model">gamification.karma.tracking</field>
<field name="view_mode">tree,form</field>
</record>
</data>
</odoo>

View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- menus in settings - technical feature required -->
<menuitem id="gamification_menu"
name="Gamification Tools"
parent="base.menu_administration"
groups="base.group_no_one" />
<menuitem id="gamification_challenge_menu"
parent="gamification_menu"
action="challenge_list_action"
sequence="0"/>
<menuitem id="gamification_goal_menu"
parent="gamification_menu"
action="goal_list_action"
sequence="10"/>
<menuitem id="gamification_definition_menu"
parent="gamification_menu"
action="goal_definition_list_action"
sequence="20"/>
<menuitem id="gamification_badge_menu"
parent="gamification_menu"
action="badge_list_action"
sequence="30"/>
<menuitem id="gamification_karma_ranks_menu"
parent="gamification_menu"
action="gamification_karma_ranks_action"
sequence="40"/>
<menuitem id="gamification_karma_tracking_menu"
parent="gamification_menu"
action="gamification_karma_tracking_action"
sequence="50"/>
</odoo>

View file

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="res_users_view_form" model="ir.ui.view">
<field name="name">res.users.view.form.inherit.gamification</field>
<field name="model">res.users</field>
<field name="inherit_id" ref="base.view_users_form"/>
<field name="arch" type="xml">
<group name="messaging" position="inside">
<field name="karma"/>
</group>
</field>
</record>
<!-- ACTIONS -->
<record id="action_current_rank_users" model="ir.actions.act_window">
<field name="name">Users</field>
<field name="res_model">res.users</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('rank_id', '=', active_id)]</field>
</record>
<record id="action_new_simplified_res_users" model="ir.actions.act_window">
<field name="name">Create User</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">res.users</field>
<field name="target">current</field>
<field name="view_id" ref="base.view_users_simple_form"/>
<field name="context">{}</field>
<field name="help">Create and manage users that will connect to the system. Users can be deactivated should there be a period of time during which they will/should not connect to the system. You can assign them groups in order to give them specific access to the applications they need to use in the system.</field>
</record>
</data>
</odoo>