Added Company filter for chart data on Home page.

This commit is contained in:
rocketdebris 2026-01-22 14:03:43 -05:00
parent f386edf769
commit 5b2e362100
3 changed files with 53 additions and 34 deletions

View file

@ -43,33 +43,32 @@ def get_task_status_options():
@frappe.whitelist() @frappe.whitelist()
def get_tasks_due(subject_filter): def get_tasks_due(subject_filter, current_company):
"""Return the number of items due today of the type of subject_filter""" """Return the number of items due today of the type of subject_filter"""
try: try:
filters = {
'subject': ['like', f'%{subject_filter}%'],
'status': ['not in', ["Template", "Completed", "Cancelled"]]
}
count = frappe.db.count("Task", filters=filters)
return build_success_response(count)
except frappe.ValidationError as ve:
return build_error_response(str(ve), 400)
except Exception as e:
return build_error_response(str(e), 500)
due_filters = {
@frappe.whitelist()
def get_tasks_completed(subject_filter):
"""Return the number of items due today marked complete of the type of subject_filter"""
try:
filters = {
'subject': ['like', f'%{subject_filter}%'], 'subject': ['like', f'%{subject_filter}%'],
'status': ['not in', ["Template", "Cancelled"]] 'status': ['not in', ["Template", "Completed", "Cancelled"]],
'company': current_company,
# Add due date filter here
} }
print("Completed Task filter", filters) completed_filters = {
count = frappe.db.count("Task", filters=filters) 'subject': ['like', f'%{subject_filter}%'],
print("Matching Records:", count) 'status': ['not in', ["Template", "Cancelled"]],
return build_success_response(count) 'company': current_company,
# Add due date filter here
}
overdue_filters = {
'subject': ['like', f'%{subject_filter}%'],
'status': ['not in', ["Template", "Completed", "Cancelled"]],
'company': current_company,
# Add overdue date filtering here
}
due_count = frappe.db.count("Task", filters=due_filters)
completed_count = frappe.db.count("Task", filters=completed_filters)
overdue_count = frappe.db.count("Task", filters=overdue_filters)
return build_success_response([due_count, completed_count, overdue_count])
except frappe.ValidationError as ve: except frappe.ValidationError as ve:
return build_error_response(str(ve), 400) return build_error_response(str(ve), 400)
except Exception as e: except Exception as e:

View file

@ -14,6 +14,8 @@ const FRAPPE_LOCK_ESTIMATE_METHOD = "custom_ui.api.db.estimates.lock_estimate";
const FRAPPE_ESTIMATE_UPDATE_RESPONSE_METHOD = "custom_ui.api.db.estimates.manual_response"; const FRAPPE_ESTIMATE_UPDATE_RESPONSE_METHOD = "custom_ui.api.db.estimates.manual_response";
const FRAPPE_GET_ESTIMATE_TEMPLATES_METHOD = "custom_ui.api.db.estimates.get_estimate_templates"; const FRAPPE_GET_ESTIMATE_TEMPLATES_METHOD = "custom_ui.api.db.estimates.get_estimate_templates";
const FRAPPE_CREATE_ESTIMATE_TEMPLATE_METHOD = "custom_ui.api.db.estimates.create_estimate_template"; const FRAPPE_CREATE_ESTIMATE_TEMPLATE_METHOD = "custom_ui.api.db.estimates.create_estimate_template";
const FRAPPE_GET_UNAPPROVED_ESTIMATES_COUNT_METHOD = "custom_ui.api.db.estimates.get_unnaproved_estimates_count";
const FRAPPE_GET_ESTIMATES_HALF_DOWN_COUNT_METHOD = "custom_ui.api.db.estimates.get_estimates_half_down_count";
// Job methods // Job methods
const FRAPPE_GET_JOB_METHOD = "custom_ui.api.db.jobs.get_job"; const FRAPPE_GET_JOB_METHOD = "custom_ui.api.db.jobs.get_job";
const FRAPPE_GET_JOBS_METHOD = "custom_ui.api.db.jobs.get_jobs_table_data"; const FRAPPE_GET_JOBS_METHOD = "custom_ui.api.db.jobs.get_jobs_table_data";
@ -29,7 +31,6 @@ const FRAPPE_GET_TASKS_METHOD = "custom_ui.api.db.tasks.get_tasks_table_data";
const FRAPPE_GET_TASKS_STATUS_OPTIONS = "custom_ui.api.db.tasks.get_task_status_options"; const FRAPPE_GET_TASKS_STATUS_OPTIONS = "custom_ui.api.db.tasks.get_task_status_options";
const FRAPPE_SET_TASK_STATUS_METHOD = "custom_ui.api.db.tasks.set_task_status"; const FRAPPE_SET_TASK_STATUS_METHOD = "custom_ui.api.db.tasks.set_task_status";
const FRAPPE_GET_TASKS_DUE_METHOD = "custom_ui.api.db.tasks.get_tasks_due"; const FRAPPE_GET_TASKS_DUE_METHOD = "custom_ui.api.db.tasks.get_tasks_due";
const FRAPPE_GET_TASKS_COMPLETED_METHOD = "custom_ui.api.db.tasks.get_tasks_completed";
// Invoice methods // Invoice methods
const FRAPPE_GET_INVOICES_METHOD = "custom_ui.api.db.invoices.get_invoice_table_data"; const FRAPPE_GET_INVOICES_METHOD = "custom_ui.api.db.invoices.get_invoice_table_data";
const FRAPPE_UPSERT_INVOICE_METHOD = "custom_ui.api.db.invoices.upsert_invoice"; const FRAPPE_UPSERT_INVOICE_METHOD = "custom_ui.api.db.invoices.upsert_invoice";
@ -264,6 +265,14 @@ class Api {
return await this.request(FRAPPE_CREATE_ESTIMATE_TEMPLATE_METHOD, { data }); return await this.request(FRAPPE_CREATE_ESTIMATE_TEMPLATE_METHOD, { data });
} }
static async getUnapprovedEstimatesCount() {
return await this.request(FRAPPE_GET_UNAPPROVED_ESTIMATES_COUNT_METHOD, {});
}
static async getEstimatesHalfDownCount() {
return await this.request(FRAPPE_GET_ESTIMATES_HALF_DOWN_COUNT_METHOD, {});
}
// ============================================================================ // ============================================================================
// JOB / PROJECT METHODS // JOB / PROJECT METHODS
// ============================================================================ // ============================================================================
@ -436,8 +445,8 @@ class Api {
return await this.request(FRAPPE_SET_TASK_STATUS_METHOD, { taskName, newStatus }); return await this.request(FRAPPE_SET_TASK_STATUS_METHOD, { taskName, newStatus });
} }
static async getTasksDue(subjectFilter) { static async getTasksDue(subjectFilter, currentCompany) {
const result = await this.request(FRAPPE_GET_TASKS_DUE_METHOD, {subjectFilter}); const result = await this.request(FRAPPE_GET_TASKS_DUE_METHOD, {subjectFilter, currentCompany});
return result; return result;
} }

View file

@ -312,7 +312,7 @@
</template> </template>
<script setup> <script setup>
import { ref, computed, onMounted } from "vue"; import { ref, computed, onMounted, watch } from "vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
//import Card from "primevue/card"; //import Card from "primevue/card";
import Card from "../common/Card.vue"; import Card from "../common/Card.vue";
@ -323,6 +323,7 @@ WateringSoil, Soil, Truck, SoilAlt } from "@iconoir/vue";
import Api from "../../api.js"; import Api from "../../api.js";
import DataUtils from "../../utils.js"; import DataUtils from "../../utils.js";
import { useNotificationStore } from "../../stores/notifications-primevue"; import { useNotificationStore } from "../../stores/notifications-primevue";
import { useCompanyStore } from "../../stores/company.js";
//import SimpleChart from "../common/SimpleChart.vue"; //import SimpleChart from "../common/SimpleChart.vue";
import TodoChart from "../common/TodoChart.vue"; import TodoChart from "../common/TodoChart.vue";
@ -360,6 +361,7 @@ const chartData = ref({
}); });
const notifications = useNotificationStore(); const notifications = useNotificationStore();
const companyStore = useCompanyStore();
// Computed values for dashboard metrics // Computed values for dashboard metrics
const totalRevenue = computed(() => "$47,250"); const totalRevenue = computed(() => "$47,250");
@ -371,17 +373,26 @@ const avgResponseTime = computed(() => 2.3);
const navigateTo = (path) => { const navigateTo = (path) => {
router.push(path); router.push(path);
}; };
const loadChartData = async() => {
chartData.value.locates.data = await Api.getTasksDue("Locate", companyStore.currentCompany);
chartData.value.permits.data = await Api.getTasksDue("Permit", companyStore.currentCompany);
chartData.value.curbing.data = await Api.getTasksDue("Curbing", companyStore.currentCompany);
chartData.value.hydroseed.data = await Api.getTasksDue("Hydroseed", companyStore.currentCompany);
//Uncomment below when we can check if half-down payments have/can been paid
//chartData.value.estimates.data = await Api.getEstimatesHalfDownCount();
};
onMounted(async() => { onMounted(async() => {
notifications.addWarning("Dashboard metrics are based on dummy data for demonstration purposes. UPDATES COMING SOON!"); notifications.addWarning("Dashboard metrics are based on dummy data for demonstration purposes. UPDATES COMING SOON!");
chartData.value.locates.data[0] = await Api.getTasksDue("Locate"); await loadChartData();
chartData.value.locates.data[1] = await Api.getTasksCompleted("Locate");
chartData.value.permits.data[0] = await Api.getTasksDue("Permit");
chartData.value.permits.data[1] = await Api.getTasksCompleted("Permit");
chartData.value.curbing.data[0] = await Api.getTasksDue("Curbing");
chartData.value.curbing.data[1] = await Api.getTasksCompleted("Curbing");
chartData.value.hydroseed.data[0] = await Api.getTasksDue("Hydroseed");
chartData.value.hydroseed.data[1] = await Api.getTasksCompleted("Hydroseed");
}); });
watch(() => companyStore.currentCompany, async (newCompany, oldCompany) => {
console.log("Wathcing for new Company");
await loadChartData();
});
</script> </script>
<style scoped> <style scoped>