Skip to content

Commit

Permalink
Merge branch '17.0' into 640-openspp-modules
Browse files Browse the repository at this point in the history
  • Loading branch information
shashikala1998 authored Nov 11, 2024
2 parents 139d65e + 0501c8e commit af96612
Show file tree
Hide file tree
Showing 16 changed files with 318 additions and 6 deletions.
Empty file added spp_dashboard_base/__init__.py
Empty file.
30 changes: 30 additions & 0 deletions spp_dashboard_base/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Part of OpenSPP. See LICENSE file for full copyright and licensing details.


{
"name": "OpenSPP Dashboard: Base",
"category": "OpenSPP",
"version": "17.0.1.0.0",
"sequence": 1,
"author": "OpenSPP.org",
"website": "https://github.com/OpenSPP/openspp-modules",
"license": "LGPL-3",
"development_status": "Beta",
"maintainers": ["reichie020212"],
"depends": [
"base",
],
"data": [],
"assets": {
"web.assets_backend": [
"spp_dashboard_base/static/src/dashboard/**/*",
"spp_dashboard_base/static/src/chart/**/*",
"spp_dashboard_base/static/src/card_board/**/*",
],
},
"demo": [],
"images": [],
"application": False,
"installable": True,
"auto_install": False,
}
3 changes: 3 additions & 0 deletions spp_dashboard_base/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"
Binary file added spp_dashboard_base/static/description/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions spp_dashboard_base/static/src/card_board/card_board.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/** @odoo-module **/

import {Component} from "@odoo/owl";

export class CardBoardComponent extends Component {}

CardBoardComponent.template = "spp_dashboard_base.CardBoardTemplate";
CardBoardComponent.props = {
title: {type: String, optional: true},
data: {type: [String, Number], optional: true},
size: {type: String, optional: true},
};
CardBoardComponent.defaultProps = {
title: "Title",
data: "Data",
size: "col-md-4",
};
26 changes: 26 additions & 0 deletions spp_dashboard_base/static/src/card_board/card_board.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates>
<t t-name="spp_dashboard_base.CardBoardTemplate">
<div t-att-class="props.size" style="padding-top: 30px;">
<div
class="oh-card"
style="box-shadow: 2px 4px 8px 2px rgba(0, 0, 0, 0.2); display: flex; justify-content: center; align-items: center; height: 100px;"
role="button"
>
<div class="oh-card-body" style="padding: 5px; width: 100%; box-sizing: border-box;">
<div
class="stat-widget-one"
style="display: flex; justify-content: center; align-items: center; height: 100%;"
>
<div class="stat_content" style="text-align: center; font-weight: bold;">
<div style="font-size: 17px;">
<t t-esc="props.data" />
</div>
<div class="stat-head" style="font-size: 14px;"><t t-esc="props.title" /></div>
</div>
</div>
</div>
</div>
</div>
</t>
</templates>
72 changes: 72 additions & 0 deletions spp_dashboard_base/static/src/chart/chart.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/** @odoo-module **/

import {Component, onMounted, onWillStart, useRef} from "@odoo/owl";
import {loadBundle} from "@web/core/assets";

export class ChartComponent extends Component {
setup() {
onMounted(() => this.renderChart());
this.canvasRef = useRef("canvas");

this.chartTitle = "";
const chartTypesWithTitle = ["pie", "doughnut"];
if (chartTypesWithTitle.includes(this.props.chart_type)) {
this.chartTitle = this.props.data_label;
}

onWillStart(async () => {
return Promise.all([
// Load external JavaScript and CSS libraries.
loadBundle({
jsLibs: [
// "/awesome_dashboard/static/lib/chart-js.4.4.4/chart.umd.min.js",
"https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js",
],
}),
]);
});
}

renderChart() {
const ctx = this.canvasRef.el.getContext("2d");

new Chart(ctx, {
type: this.props.chart_type,
data: {
labels: this.props.labels,
datasets: [
{
label: this.props.data_label,
data: this.props.data,
backgroundColor: this.props.backgroundColor,
hoverOffset: 2,
},
],
},
options: {...this.props.options},
});
}
}

ChartComponent.template = "spp_dashboard_base.ChartComponentTemplate";
ChartComponent.props = {
chart_type: {type: String, optional: true},
labels: {type: Array, optional: true},
data_label: {type: String, optional: true},
data: {type: Array, optional: true},
backgroundColor: {type: Array, optional: true},
options: {type: Object, optional: true},
size: {type: String, optional: true},
};
ChartComponent.defaultProps = {
chart_type: "pie",
labels: ["Red", "Blue", "Yellow"],
data_label: "Number of Colors",
data: [300, 50, 150],
backgroundColor: ["rgb(255, 99, 132)", "rgb(54, 162, 235)", "rgb(255, 205, 86)"],
options: {
maintainAspectRatio: true,
aspectRatio: 2,
},
size: "col-md-6",
};
18 changes: 18 additions & 0 deletions spp_dashboard_base/static/src/chart/chart.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates>
<t t-name="spp_dashboard_base.ChartComponentTemplate">
<style>
.pie-chart-container {
border: 2px solid #000;
border-radius: 10px;
margin-top : 2em;
}
</style>
<div class="container" t-att-class="props.size">
<div class="pie-chart-container">
<h3 style="text-align: center;"><t t-esc="chartTitle" /></h3>
<canvas id="myChart" t-ref="canvas" />
</div>
</div>
</t>
</templates>
28 changes: 28 additions & 0 deletions spp_dashboard_base/static/src/dashboard/dashboard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/** @odoo-module **/
import {Component, onWillStart, useState} from "@odoo/owl";
import {CardBoardComponent} from "../card_board/card_board";
import {ChartComponent} from "../chart/chart";
import {registry} from "@web/core/registry";
import {useService} from "@web/core/utils/hooks";

export class SppDashboard extends Component {
setup() {
super.setup();
this.orm = useService("orm");
this.state = useState({hierarchy: []});
this.card_board_data = {};
onWillStart(this.onWillStart);
this.dashboard_title = "Dashboard";
}

async onWillStart() {
// Super this function to get data from the server
// sample
// this.dashboard_data = await this.orm.call("res.partner", "get_data", []);
}
}

SppDashboard.template = "spp_dashboard_base.dashboard_page";
SppDashboard.components = {ChartComponent, CardBoardComponent};

registry.category("actions").add("spp_dashboard_tag", SppDashboard);
14 changes: 14 additions & 0 deletions spp_dashboard_base/static/src/dashboard/dashboard.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates>
<t t-name="spp_dashboard_base.dashboard_page">
<div class="main" style="height: 100vh; overflow-y: auto;">
<div class="title" name="title">
<center>
<h1><t t-esc="dashboard_title" /></h1>
</center>
</div>
<div class="container dashboard-container" name="dashboard-container">
</div>
</div>
</t>
</templates>
4 changes: 3 additions & 1 deletion spp_farmer_registry_base/models/agricultural_activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ class AgriculturalActivity(models.Model):
],
)

species_id = fields.Many2one("spp.farm.species", string="Species", domain="[('species_type', '=', activity_type)]")
species_id = fields.Many2one(
"spp.farm.species", ondelete="restrict", string="Species", domain="[('species_type', '=', activity_type)]"
)

@api.onchange("crop_farm_id")
def _onchange_farm_id(self):
Expand Down
43 changes: 40 additions & 3 deletions spp_farmer_registry_demo/models/generate_farmer_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from odoo import Command, api, fields, models

from odoo.addons.queue_job.delay import group
from odoo.addons.spp_base_demo.locale_providers import create_faker

from .. import tools
Expand Down Expand Up @@ -57,16 +58,52 @@ class SPPGenerateFarmerData(models.Model):
required=True,
)

locked = fields.Boolean(default=False)
locked_reason = fields.Char(readonly=True)

GROUPS_PER_BATCH = 100

def generate_sample_data(self):
batches = math.ceil(self.num_groups / 1000)
batches = math.ceil(self.num_groups / self.GROUPS_PER_BATCH)

self.locked = True
self.locked_reason = "Generating Sample Data"
num_groups = self.num_groups

jobs = []

for _ in range(0, batches):
jobs.append(self.delayable()._generate_sample_data(res=self, num_groups=num_groups))
batch_num_groups = min(num_groups, self.GROUPS_PER_BATCH)
num_groups -= batch_num_groups
# self.with_delay()._generate_sample_data(res_id=self.id)
self._generate_sample_data(res=self)
# self._generate_sample_data(res=self)

main_job = group(*jobs)
main_job.on_done(self.delayable()._mark_done())
main_job.delay()

def _mark_done(self):
self.ensure_one()
self.locked = False
self.locked_reason = ""

def refresh_page(self):
"""
The function `refresh_page` returns a dictionary with the type and tag values to reload the
page.
:return: The code is returning a dictionary with two key-value pairs. The "type" key has the
value "ir.actions.client" and the "tag" key has the value "reload".
"""
return {
"type": "ir.actions.client",
"tag": "reload",
}

@api.model
def _generate_sample_data(self, **kwargs):
res = kwargs.get("res")
num_groups = kwargs.get("num_groups")

kind_farm_id = self.env.ref("spp_farmer_registry_base.kind_farm").id

Expand All @@ -77,7 +114,7 @@ def _generate_sample_data(self, **kwargs):
sex_choices = [option.value for option in options]
sex_choice_range = sex_choices * 50

num_groups = min(res.num_groups, 1000)
num_groups = min(num_groups, self.GROUPS_PER_BATCH)

for i in range(0, num_groups):
group_id = res._generate_group_data(i, fake, sex_choice_range, kind_farm_id)
Expand Down
19 changes: 18 additions & 1 deletion spp_farmer_registry_demo/views/generate_farmer_data_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,25 @@
<header>
<field name="state" widget="statusbar" statusbar_visible="draft,generate" />
</header>
<field name="locked" invisible="True" />
<div
class="alert alert-warning text-center o_form_header"
role="status"
invisible="not locked"
>
<span>Warning: Operation in progress: </span>
<field name="locked_reason" class="o_stat_value" />
<button
name="refresh_page"
type="object"
class="btn_warning"
icon="fa-refresh"
title="Refresh Page"
string="Refresh"
/>
</div>
<sheet>
<div class="oe_button_box" name="button_box">
<div class="oe_button_box" name="button_box" invisible="locked">
<button
type="object"
class="oe_stat_button"
Expand Down
6 changes: 5 additions & 1 deletion spp_programs/views/cycle_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ Part of OpenSPP. See LICENSE file for full copyright and licensing details.
</xpath>
<xpath expr="//button[@name='open_entitlements_form']" position="attributes">
<attribute name="invisible">entitlements_count == 0</attribute>
<attribute name="icon">fa-calculator</attribute>
</xpath>
<xpath expr="//button[@name='open_entitlements_form']" position="after">
<button
type="object"
class="oe_stat_button"
icon="fa-folder-open-o"
icon="fa-calculator"
name="open_entitlements_form"
invisible="inkind_entitlements_count == 0"
>
Expand Down Expand Up @@ -62,6 +63,9 @@ Part of OpenSPP. See LICENSE file for full copyright and licensing details.
<attribute name="string">Copy New Beneficiaries from Program</attribute>
<attribute name="title">Copy New Beneficiaries from Program</attribute>
</xpath>
<xpath expr="//button[@name='open_payments_form']" position="attributes">
<attribute name="icon">fa-file-text-o</attribute>
</xpath>
</field>
</record>

Expand Down
29 changes: 29 additions & 0 deletions spp_programs_compliance_criteria/models/g2p_cycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class G2pCycle(models.Model):
_inherit = "g2p.cycle"

allow_filter_compliance_criteria = fields.Boolean(compute="_compute_allow_filter_compliance_criteria")
all_members_count = fields.Integer(string="# Enrollments", readonly=True, compute="_compute_all_members_count")

@api.depends("program_id", "program_id.compliance_managers")
def _compute_allow_filter_compliance_criteria(self):
Expand Down Expand Up @@ -36,3 +37,31 @@ def _get_compliance_criteria_domain(self):
membership = self.cycle_membership_ids if self.cycle_membership_ids else None
domain.append(manager_ref._prepare_eligible_domain(membership))
return OR(domain)

def _compute_all_members_count(self):
for rec in self:
domain = rec._get_beneficiaries_domain(None)
members_count = self.env["g2p.cycle.membership"].search_count(domain)
rec.update({"all_members_count": members_count})

def open_all_members_form(self):
self.ensure_one()

action = {
"name": _("Cycle Members"),
"type": "ir.actions.act_window",
"res_model": "g2p.cycle.membership",
"context": {
"create": False,
"default_cycle_id": self.id,
},
"view_mode": "list,form",
"domain": [("cycle_id", "=", self.id)],
}
return action

def open_members_form(self):
self.ensure_one()
action = super().open_members_form()
action["name"] = _("Cycle Beneficiaries")
return action
Loading

0 comments on commit af96612

Please sign in to comment.