From 8280774762c45dce1667d86157389a1f408377b1 Mon Sep 17 00:00:00 2001
From: Ali <010109ali@gmail.com>
Date: Tue, 19 Aug 2025 12:55:32 +0400
Subject: [PATCH] new sport and lottery report
---
.../sport_and_lottery_report/__init__.py | 0
.../sport_and_lottery_report.js | 71 ++++++++++
.../sport_and_lottery_report.json | 33 +++++
.../sport_and_lottery_report.py | 125 ++++++++++++++++++
4 files changed, 229 insertions(+)
create mode 100644 taxes_az/taxes_az/report/sport_and_lottery_report/__init__.py
create mode 100644 taxes_az/taxes_az/report/sport_and_lottery_report/sport_and_lottery_report.js
create mode 100644 taxes_az/taxes_az/report/sport_and_lottery_report/sport_and_lottery_report.json
create mode 100644 taxes_az/taxes_az/report/sport_and_lottery_report/sport_and_lottery_report.py
diff --git a/taxes_az/taxes_az/report/sport_and_lottery_report/__init__.py b/taxes_az/taxes_az/report/sport_and_lottery_report/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/taxes_az/taxes_az/report/sport_and_lottery_report/sport_and_lottery_report.js b/taxes_az/taxes_az/report/sport_and_lottery_report/sport_and_lottery_report.js
new file mode 100644
index 0000000..67fd4d0
--- /dev/null
+++ b/taxes_az/taxes_az/report/sport_and_lottery_report/sport_and_lottery_report.js
@@ -0,0 +1,71 @@
+frappe.query_reports["Sport and Lottery Report"] = {
+ "filters": [
+ {
+ "fieldname": "company",
+ "label": __("Company"),
+ "fieldtype": "Link",
+ "options": "Company",
+ "default": frappe.defaults.get_user_default("Company"),
+ "reqd": 1
+ },
+ {
+ "fieldname": "from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
+ "reqd": 1
+ },
+ {
+ "fieldname": "to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.get_today(),
+ "reqd": 1
+ }
+ ],
+ "columns": [
+ {
+ "label": __("Sales Invoice"),
+ "fieldname": "sales_invoice",
+ "fieldtype": "Link",
+ "options": "Sales Invoice",
+ "width": 200
+ },
+ {
+ "label": __("Posting Date"),
+ "fieldname": "posting_date",
+ "fieldtype": "Date",
+ "width": 120
+ },
+ {
+ "label": __("Grand Total"),
+ "fieldname": "grand_total",
+ "fieldtype": "Currency",
+ "options": "currency",
+ "width": 150
+ },
+ {
+ "label": __("Amount up to 500"),
+ "fieldname": "amount_up_to_500",
+ "fieldtype": "Currency",
+ "options": "currency",
+ "width": 180
+ },
+ {
+ "label": __("Amount over 500"),
+ "fieldname": "amount_over_500",
+ "fieldtype": "Currency",
+ "options": "currency",
+ "width": 180
+ }
+ ],
+ "formatter": function(value, row, column, data, default_formatter) {
+ value = default_formatter(value, row, column, data);
+ if (column.fieldname === "amount_up_to_500" && data.amount_up_to_500 > 0) {
+ value = "" + value + "";
+ } else if (column.fieldname === "amount_over_500" && data.amount_over_500 > 0) {
+ value = "" + value + "";
+ }
+ return value;
+ }
+};
diff --git a/taxes_az/taxes_az/report/sport_and_lottery_report/sport_and_lottery_report.json b/taxes_az/taxes_az/report/sport_and_lottery_report/sport_and_lottery_report.json
new file mode 100644
index 0000000..f2603d5
--- /dev/null
+++ b/taxes_az/taxes_az/report/sport_and_lottery_report/sport_and_lottery_report.json
@@ -0,0 +1,33 @@
+{
+ "add_total_row": 0,
+ "columns": [],
+ "creation": "2025-08-18 17:55:54.332106",
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "letterhead": null,
+ "modified": "2025-08-18 17:56:15.489704",
+ "modified_by": "Administrator",
+ "module": "Taxes Az",
+ "name": "Sport and Lottery Report",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Sales Invoice",
+ "report_name": "Sport and Lottery Report",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "Accounts User"
+ },
+ {
+ "role": "Accounts Manager"
+ },
+ {
+ "role": "Employee Self Service"
+ }
+ ],
+ "timeout": 0
+}
\ No newline at end of file
diff --git a/taxes_az/taxes_az/report/sport_and_lottery_report/sport_and_lottery_report.py b/taxes_az/taxes_az/report/sport_and_lottery_report/sport_and_lottery_report.py
new file mode 100644
index 0000000..8755908
--- /dev/null
+++ b/taxes_az/taxes_az/report/sport_and_lottery_report/sport_and_lottery_report.py
@@ -0,0 +1,125 @@
+import frappe
+from frappe import _
+
+def execute(filters=None):
+ columns, data = [], []
+ columns = get_columns()
+ data = get_data(filters)
+ return columns, data
+
+def get_columns():
+ """Defines the columns for the report."""
+ return [
+ {
+ "label": _("Sales Invoice"),
+ "fieldname": "sales_invoice",
+ "fieldtype": "Link",
+ "options": "Sales Invoice",
+ "width": 200
+ },
+ {
+ "label": _("Posting Date"),
+ "fieldname": "posting_date",
+ "fieldtype": "Date",
+ "width": 120
+ },
+ {
+ "label": _("Grand Total"),
+ "fieldname": "grand_total",
+ "fieldtype": "Currency",
+ "options": "currency",
+ "width": 150
+ },
+ {
+ "label": _("Amount up to 500"),
+ "fieldname": "amount_up_to_500",
+ "fieldtype": "Currency",
+ "options": "currency",
+ "width": 180
+ },
+ {
+ "label": _("Amount over 500"),
+ "fieldname": "amount_over_500",
+ "fieldtype": "Currency",
+ "options": "currency",
+ "width": 180
+ },
+ {
+ "label": _("Currency"),
+ "fieldname": "currency",
+ "fieldtype": "Link",
+ "options": "Currency",
+ "hidden": 1
+ }
+ ]
+
+def get_data(filters):
+ """Fetches and processes the report data."""
+ conditions = get_conditions(filters)
+
+ # The item groups to filter by
+ target_item_groups = ["İdman və mərc oyunları", "Lotoreya oyunları"]
+
+ # Fetching the data using Frappe's Query Builder
+ si = frappe.qb.DocType("Sales Invoice")
+ sii = frappe.qb.DocType("Sales Invoice Item")
+ item = frappe.qb.DocType("Item")
+
+ query = (
+ frappe.qb.from_(si)
+ .inner_join(sii)
+ .on(si.name == sii.parent)
+ .inner_join(item)
+ .on(sii.item_code == item.name)
+ .select(
+ si.name.as_("sales_invoice"),
+ si.posting_date,
+ si.grand_total,
+ si.currency,
+ sii.amount
+ )
+ .where(
+ (si.docstatus == 1) &
+ (item.item_group.isin(target_item_groups)) &
+ (si.company == filters.get("company")) &
+ (si.posting_date.between(filters.get("from_date"), filters.get("to_date")))
+ )
+ )
+
+ # Execute the query
+ invoice_items = query.run(as_dict=True)
+
+ # Process the data to aggregate amounts per invoice
+ processed_data = {}
+ for item in invoice_items:
+ doc_name = item.sales_invoice
+ if doc_name not in processed_data:
+ processed_data[doc_name] = {
+ "sales_invoice": doc_name,
+ "posting_date": item.posting_date,
+ "grand_total": item.grand_total,
+ "currency": item.currency,
+ "amount_up_to_500": 0,
+ "amount_over_500": 0,
+ }
+
+ # Distribute the item amount into the correct bucket
+ if item.amount <= 500:
+ processed_data[doc_name]["amount_up_to_500"] += item.amount
+ else:
+ processed_data[doc_name]["amount_over_500"] += item.amount
+
+ # Return the processed data as a list of dictionaries
+ return list(processed_data.values())
+
+def get_conditions(filters):
+ """Builds SQL conditions from filters."""
+ conditions = ""
+ if filters.get("company"):
+ conditions += f" AND si.company = '{filters.get('company')}'"
+ if filters.get("from_date"):
+ conditions += f" AND si.posting_date >= '{filters.get('from_date')}'"
+ if filters.get("to_date"):
+ conditions += f" AND si.posting_date <= '{filters.get('to_date')}'"
+ return conditions
+