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 +