tundebabzy | c897825 | 2018-02-12 10:34:50 +0100 | [diff] [blame] | 1 | import frappe |
Gursheen Anand | 6c11ca1 | 2023-07-12 14:43:18 +0530 | [diff] [blame] | 2 | from frappe.query_builder.custom import ConstantColumn |
Gursheen Anand | f5027fd | 2023-07-12 16:42:58 +0530 | [diff] [blame] | 3 | from frappe.query_builder.functions import Sum |
Sagar Vora | 30e4052 | 2023-07-04 17:41:30 +0530 | [diff] [blame] | 4 | from frappe.utils import flt, formatdate, get_datetime_str, get_table_name |
Gursheen Anand | 6c11ca1 | 2023-07-12 14:43:18 +0530 | [diff] [blame] | 5 | from pypika import Order |
Chillar Anand | 915b343 | 2021-09-02 16:44:59 +0530 | [diff] [blame] | 6 | |
tundebabzy | c897825 | 2018-02-12 10:34:50 +0100 | [diff] [blame] | 7 | from erpnext import get_company_currency, get_default_company |
Gursheen Anand | 6c11ca1 | 2023-07-12 14:43:18 +0530 | [diff] [blame] | 8 | from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( |
Gursheen Anand | c084fe6 | 2023-07-14 11:05:50 +0530 | [diff] [blame] | 9 | get_accounting_dimensions, |
Gursheen Anand | 6c11ca1 | 2023-07-12 14:43:18 +0530 | [diff] [blame] | 10 | get_dimension_with_children, |
| 11 | ) |
Prateeksha Singh | 8ecfaaa | 2018-07-18 18:03:27 +0530 | [diff] [blame] | 12 | from erpnext.accounts.doctype.fiscal_year.fiscal_year import get_from_and_to_date |
Gursheen Anand | 944244c | 2023-07-14 10:50:12 +0530 | [diff] [blame] | 13 | from erpnext.accounts.party import get_party_account |
Chillar Anand | 915b343 | 2021-09-02 16:44:59 +0530 | [diff] [blame] | 14 | from erpnext.setup.utils import get_exchange_rate |
tundebabzy | c897825 | 2018-02-12 10:34:50 +0100 | [diff] [blame] | 15 | |
| 16 | __exchange_rates = {} |
tundebabzy | c897825 | 2018-02-12 10:34:50 +0100 | [diff] [blame] | 17 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 18 | |
tundebabzy | c897825 | 2018-02-12 10:34:50 +0100 | [diff] [blame] | 19 | def get_currency(filters): |
| 20 | """ |
| 21 | Returns a dictionary containing currency information. The keys of the dict are |
| 22 | - company: The company for which we are fetching currency information. if no |
| 23 | company is specified, it will fallback to the default company. |
| 24 | - company currency: The functional currency of the said company. |
| 25 | - presentation currency: The presentation currency to use. Only currencies that |
| 26 | have been used for transactions will be allowed. |
| 27 | - report date: The report date. |
| 28 | :param filters: Report filters |
| 29 | :type filters: dict |
| 30 | |
| 31 | :return: str - Currency |
| 32 | """ |
| 33 | company = get_appropriate_company(filters) |
| 34 | company_currency = get_company_currency(company) |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 35 | presentation_currency = ( |
| 36 | filters["presentation_currency"] if filters.get("presentation_currency") else company_currency |
| 37 | ) |
Prateeksha Singh | 8ecfaaa | 2018-07-18 18:03:27 +0530 | [diff] [blame] | 38 | |
ruthra kumar | a6794c3 | 2022-12-06 13:44:54 +0530 | [diff] [blame] | 39 | report_date = filters.get("to_date") or filters.get("period_end_date") |
Prateeksha Singh | 8ecfaaa | 2018-07-18 18:03:27 +0530 | [diff] [blame] | 40 | |
| 41 | if not report_date: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 42 | fiscal_year_to_date = get_from_and_to_date(filters.get("to_fiscal_year"))["to_date"] |
Prateeksha Singh | 8ecfaaa | 2018-07-18 18:03:27 +0530 | [diff] [blame] | 43 | report_date = formatdate(get_datetime_str(fiscal_year_to_date), "dd-MM-yyyy") |
tundebabzy | c897825 | 2018-02-12 10:34:50 +0100 | [diff] [blame] | 44 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 45 | currency_map = dict( |
| 46 | company=company, |
| 47 | company_currency=company_currency, |
| 48 | presentation_currency=presentation_currency, |
| 49 | report_date=report_date, |
| 50 | ) |
tundebabzy | c897825 | 2018-02-12 10:34:50 +0100 | [diff] [blame] | 51 | |
| 52 | return currency_map |
| 53 | |
| 54 | |
| 55 | def convert(value, from_, to, date): |
| 56 | """ |
| 57 | convert `value` from `from_` to `to` on `date` |
| 58 | :param value: Amount to be converted |
| 59 | :param from_: Currency of `value` |
| 60 | :param to: Currency to convert to |
| 61 | :param date: exchange rate as at this date |
| 62 | :return: Result of converting `value` |
| 63 | """ |
| 64 | rate = get_rate_as_at(date, from_, to) |
Zarrar | 3523b77 | 2018-08-14 16:28:14 +0530 | [diff] [blame] | 65 | converted_value = flt(value) / (rate or 1) |
tundebabzy | c897825 | 2018-02-12 10:34:50 +0100 | [diff] [blame] | 66 | return converted_value |
| 67 | |
| 68 | |
| 69 | def get_rate_as_at(date, from_currency, to_currency): |
| 70 | """ |
| 71 | Gets exchange rate as at `date` for `from_currency` - `to_currency` exchange rate. |
| 72 | This calls `get_exchange_rate` so that we can get the correct exchange rate as per |
| 73 | the user's Accounts Settings. |
| 74 | It is made efficient by memoising results to `__exchange_rates` |
| 75 | :param date: exchange rate as at this date |
| 76 | :param from_currency: Base currency |
| 77 | :param to_currency: Quote currency |
| 78 | :return: Retrieved exchange rate |
| 79 | """ |
Prateeksha Singh | 8ecfaaa | 2018-07-18 18:03:27 +0530 | [diff] [blame] | 80 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 81 | rate = __exchange_rates.get("{0}-{1}@{2}".format(from_currency, to_currency, date)) |
tundebabzy | c897825 | 2018-02-12 10:34:50 +0100 | [diff] [blame] | 82 | if not rate: |
| 83 | rate = get_exchange_rate(from_currency, to_currency, date) or 1 |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 84 | __exchange_rates["{0}-{1}@{2}".format(from_currency, to_currency, date)] = rate |
tundebabzy | c897825 | 2018-02-12 10:34:50 +0100 | [diff] [blame] | 85 | |
| 86 | return rate |
| 87 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 88 | |
Deepesh Garg | 4d07e20 | 2023-07-09 20:16:12 +0530 | [diff] [blame] | 89 | def convert_to_presentation_currency(gl_entries, currency_info): |
tundebabzy | c897825 | 2018-02-12 10:34:50 +0100 | [diff] [blame] | 90 | """ |
| 91 | Take a list of GL Entries and change the 'debit' and 'credit' values to currencies |
| 92 | in `currency_info`. |
| 93 | :param gl_entries: |
| 94 | :param currency_info: |
| 95 | :return: |
| 96 | """ |
| 97 | converted_gl_list = [] |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 98 | presentation_currency = currency_info["presentation_currency"] |
| 99 | company_currency = currency_info["company_currency"] |
tundebabzy | c897825 | 2018-02-12 10:34:50 +0100 | [diff] [blame] | 100 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 101 | account_currencies = list(set(entry["account_currency"] for entry in gl_entries)) |
Nabin Hait | 111183d | 2020-08-22 12:31:06 +0530 | [diff] [blame] | 102 | |
tundebabzy | c897825 | 2018-02-12 10:34:50 +0100 | [diff] [blame] | 103 | for entry in gl_entries: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 104 | debit = flt(entry["debit"]) |
| 105 | credit = flt(entry["credit"]) |
| 106 | debit_in_account_currency = flt(entry["debit_in_account_currency"]) |
| 107 | credit_in_account_currency = flt(entry["credit_in_account_currency"]) |
| 108 | account_currency = entry["account_currency"] |
tundebabzy | c897825 | 2018-02-12 10:34:50 +0100 | [diff] [blame] | 109 | |
Afshan | 4d61fa2 | 2021-05-25 19:16:02 +0530 | [diff] [blame] | 110 | if len(account_currencies) == 1 and account_currency == presentation_currency: |
ruthra kumar | 914b230 | 2023-01-02 14:33:14 +0530 | [diff] [blame] | 111 | entry["debit"] = debit_in_account_currency |
| 112 | entry["credit"] = credit_in_account_currency |
Afshan | 4d61fa2 | 2021-05-25 19:16:02 +0530 | [diff] [blame] | 113 | else: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 114 | date = currency_info["report_date"] |
Deepesh Garg | ceaa804 | 2021-09-05 17:21:29 +0530 | [diff] [blame] | 115 | converted_debit_value = convert(debit, presentation_currency, company_currency, date) |
| 116 | converted_credit_value = convert(credit, presentation_currency, company_currency, date) |
tundebabzy | c897825 | 2018-02-12 10:34:50 +0100 | [diff] [blame] | 117 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 118 | if entry.get("debit"): |
| 119 | entry["debit"] = converted_debit_value |
Rohit Waghchaure | 376db4f | 2019-04-18 22:01:33 +0530 | [diff] [blame] | 120 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 121 | if entry.get("credit"): |
| 122 | entry["credit"] = converted_credit_value |
tundebabzy | c897825 | 2018-02-12 10:34:50 +0100 | [diff] [blame] | 123 | |
tundebabzy | c897825 | 2018-02-12 10:34:50 +0100 | [diff] [blame] | 124 | converted_gl_list.append(entry) |
| 125 | |
| 126 | return converted_gl_list |
| 127 | |
| 128 | |
| 129 | def get_appropriate_company(filters): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 130 | if filters.get("company"): |
| 131 | company = filters["company"] |
tundebabzy | c897825 | 2018-02-12 10:34:50 +0100 | [diff] [blame] | 132 | else: |
| 133 | company = get_default_company() |
| 134 | |
| 135 | return company |
Rohit Waghchaure | 1d6f2c3 | 2019-04-23 18:33:01 +0530 | [diff] [blame] | 136 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 137 | |
Rohit Waghchaure | 1d6f2c3 | 2019-04-23 18:33:01 +0530 | [diff] [blame] | 138 | @frappe.whitelist() |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 139 | def get_invoiced_item_gross_margin( |
| 140 | sales_invoice=None, item_code=None, company=None, with_item_data=False |
| 141 | ): |
Rohit Waghchaure | 1d6f2c3 | 2019-04-23 18:33:01 +0530 | [diff] [blame] | 142 | from erpnext.accounts.report.gross_profit.gross_profit import GrossProfitGenerator |
| 143 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 144 | sales_invoice = sales_invoice or frappe.form_dict.get("sales_invoice") |
| 145 | item_code = item_code or frappe.form_dict.get("item_code") |
| 146 | company = company or frappe.get_cached_value("Sales Invoice", sales_invoice, "company") |
Rohit Waghchaure | 1d6f2c3 | 2019-04-23 18:33:01 +0530 | [diff] [blame] | 147 | |
| 148 | filters = { |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 149 | "sales_invoice": sales_invoice, |
| 150 | "item_code": item_code, |
| 151 | "company": company, |
| 152 | "group_by": "Invoice", |
Rohit Waghchaure | 1d6f2c3 | 2019-04-23 18:33:01 +0530 | [diff] [blame] | 153 | } |
| 154 | |
| 155 | gross_profit_data = GrossProfitGenerator(filters) |
Rohit Waghchaure | 7bee502 | 2019-05-08 15:31:29 +0530 | [diff] [blame] | 156 | result = gross_profit_data.grouped_data |
| 157 | if not with_item_data: |
Ankush Menat | 9891780 | 2021-06-11 18:40:22 +0530 | [diff] [blame] | 158 | result = sum(d.gross_profit for d in result) |
Rohit Waghchaure | 1d6f2c3 | 2019-04-23 18:33:01 +0530 | [diff] [blame] | 159 | |
Rohit Waghchaure | 7bee502 | 2019-05-08 15:31:29 +0530 | [diff] [blame] | 160 | return result |
Gursheen Anand | cbef6c3 | 2023-07-10 18:39:35 +0530 | [diff] [blame] | 161 | |
| 162 | |
Gursheen Anand | 6c11ca1 | 2023-07-12 14:43:18 +0530 | [diff] [blame] | 163 | def get_query_columns(report_columns): |
| 164 | if not report_columns: |
| 165 | return "" |
| 166 | |
| 167 | columns = [] |
| 168 | for column in report_columns: |
| 169 | fieldname = column["fieldname"] |
| 170 | |
| 171 | if doctype := column.get("_doctype"): |
| 172 | columns.append(f"`{get_table_name(doctype)}`.`{fieldname}`") |
| 173 | else: |
| 174 | columns.append(fieldname) |
| 175 | |
Gursheen Anand | 0d89bfa | 2023-07-14 13:03:22 +0530 | [diff] [blame] | 176 | return columns |
Gursheen Anand | 6c11ca1 | 2023-07-12 14:43:18 +0530 | [diff] [blame] | 177 | |
| 178 | |
| 179 | def get_values_for_columns(report_columns, report_row): |
| 180 | values = {} |
| 181 | |
| 182 | if not report_columns: |
| 183 | return values |
| 184 | |
| 185 | for column in report_columns: |
| 186 | fieldname = column["fieldname"] |
| 187 | values[fieldname] = report_row.get(fieldname) |
| 188 | |
| 189 | return values |
| 190 | |
| 191 | |
Gursheen Anand | cbef6c3 | 2023-07-10 18:39:35 +0530 | [diff] [blame] | 192 | def get_party_details(party_type, party_list): |
| 193 | party_details = {} |
| 194 | party = frappe.qb.DocType(party_type) |
| 195 | query = frappe.qb.from_(party).select(party.name, party.tax_id).where(party.name.isin(party_list)) |
| 196 | if party_type == "Supplier": |
| 197 | query = query.select(party.supplier_group) |
| 198 | else: |
| 199 | query = query.select(party.customer_group, party.territory) |
| 200 | |
| 201 | party_detail_list = query.run(as_dict=True) |
| 202 | for party_dict in party_detail_list: |
| 203 | party_details[party_dict.name] = party_dict |
| 204 | return party_details |
| 205 | |
| 206 | |
| 207 | def get_taxes_query(invoice_list, doctype, parenttype): |
| 208 | taxes = frappe.qb.DocType(doctype) |
| 209 | |
| 210 | query = ( |
| 211 | frappe.qb.from_(taxes) |
| 212 | .select(taxes.account_head) |
| 213 | .distinct() |
| 214 | .where( |
| 215 | (taxes.parenttype == parenttype) |
| 216 | & (taxes.docstatus == 1) |
| 217 | & (taxes.account_head.isnotnull()) |
| 218 | & (taxes.parent.isin([inv.name for inv in invoice_list])) |
| 219 | ) |
| 220 | .orderby(taxes.account_head) |
| 221 | ) |
| 222 | |
| 223 | if doctype == "Purchase Taxes and Charges": |
| 224 | return query.where(taxes.category.isin(["Total", "Valuation and Total"])) |
| 225 | elif doctype == "Sales Taxes and Charges": |
Gursheen Anand | f5027fd | 2023-07-12 16:42:58 +0530 | [diff] [blame] | 226 | return query |
Gursheen Anand | cbef6c3 | 2023-07-10 18:39:35 +0530 | [diff] [blame] | 227 | return query.where(taxes.charge_type.isin(["On Paid Amount", "Actual"])) |
Gursheen Anand | d5aa0e3 | 2023-07-11 14:47:23 +0530 | [diff] [blame] | 228 | |
| 229 | |
Gursheen Anand | bf08aa7 | 2023-07-12 17:17:58 +0530 | [diff] [blame] | 230 | def get_journal_entries(filters, args): |
Gursheen Anand | 6c11ca1 | 2023-07-12 14:43:18 +0530 | [diff] [blame] | 231 | je = frappe.qb.DocType("Journal Entry") |
| 232 | journal_account = frappe.qb.DocType("Journal Entry Account") |
| 233 | query = ( |
| 234 | frappe.qb.from_(je) |
| 235 | .inner_join(journal_account) |
| 236 | .on(je.name == journal_account.parent) |
| 237 | .select( |
| 238 | je.voucher_type.as_("doctype"), |
| 239 | je.name, |
| 240 | je.posting_date, |
| 241 | journal_account.account.as_(args.account), |
| 242 | journal_account.party.as_(args.party), |
| 243 | journal_account.party.as_(args.party_name), |
| 244 | je.bill_no, |
| 245 | je.bill_date, |
| 246 | je.remark.as_("remarks"), |
| 247 | je.total_amount.as_("base_net_total"), |
| 248 | je.total_amount.as_("base_grand_total"), |
| 249 | je.mode_of_payment, |
| 250 | journal_account.project, |
| 251 | ) |
Gursheen Anand | 944244c | 2023-07-14 10:50:12 +0530 | [diff] [blame] | 252 | .where( |
| 253 | (je.voucher_type == "Journal Entry") |
ruthra kumar | 0f1be03 | 2024-01-03 20:56:12 +0530 | [diff] [blame] | 254 | & (je.docstatus == 1) |
Gursheen Anand | 944244c | 2023-07-14 10:50:12 +0530 | [diff] [blame] | 255 | & (journal_account.party == filters.get(args.party)) |
| 256 | & (journal_account.account.isin(args.party_account)) |
| 257 | ) |
Gursheen Anand | 6c11ca1 | 2023-07-12 14:43:18 +0530 | [diff] [blame] | 258 | .orderby(je.posting_date, je.name, order=Order.desc) |
Gursheen Anand | d5aa0e3 | 2023-07-11 14:47:23 +0530 | [diff] [blame] | 259 | ) |
Deepesh Garg | 92e503f | 2023-08-29 20:45:57 +0530 | [diff] [blame] | 260 | query = apply_common_conditions(filters, query, doctype="Journal Entry", payments=True) |
| 261 | |
Gursheen Anand | f5027fd | 2023-07-12 16:42:58 +0530 | [diff] [blame] | 262 | journal_entries = query.run(as_dict=True) |
Gursheen Anand | 6c11ca1 | 2023-07-12 14:43:18 +0530 | [diff] [blame] | 263 | return journal_entries |
Gursheen Anand | d5aa0e3 | 2023-07-11 14:47:23 +0530 | [diff] [blame] | 264 | |
| 265 | |
Gursheen Anand | bf08aa7 | 2023-07-12 17:17:58 +0530 | [diff] [blame] | 266 | def get_payment_entries(filters, args): |
Gursheen Anand | 6c11ca1 | 2023-07-12 14:43:18 +0530 | [diff] [blame] | 267 | pe = frappe.qb.DocType("Payment Entry") |
| 268 | query = ( |
| 269 | frappe.qb.from_(pe) |
| 270 | .select( |
| 271 | ConstantColumn("Payment Entry").as_("doctype"), |
| 272 | pe.name, |
| 273 | pe.posting_date, |
Gursheen Anand | b181813 | 2023-07-27 10:08:26 +0530 | [diff] [blame] | 274 | pe[args.account_fieldname].as_(args.account), |
Gursheen Anand | 6c11ca1 | 2023-07-12 14:43:18 +0530 | [diff] [blame] | 275 | pe.party.as_(args.party), |
| 276 | pe.party_name.as_(args.party_name), |
| 277 | pe.remarks, |
| 278 | pe.paid_amount.as_("base_net_total"), |
| 279 | pe.paid_amount_after_tax.as_("base_grand_total"), |
| 280 | pe.mode_of_payment, |
| 281 | pe.project, |
| 282 | pe.cost_center, |
| 283 | ) |
Gursheen Anand | b181813 | 2023-07-27 10:08:26 +0530 | [diff] [blame] | 284 | .where( |
ruthra kumar | 0f1be03 | 2024-01-03 20:56:12 +0530 | [diff] [blame] | 285 | (pe.docstatus == 1) |
| 286 | & (pe.party == filters.get(args.party)) |
| 287 | & (pe[args.account_fieldname].isin(args.party_account)) |
Gursheen Anand | b181813 | 2023-07-27 10:08:26 +0530 | [diff] [blame] | 288 | ) |
Gursheen Anand | 6c11ca1 | 2023-07-12 14:43:18 +0530 | [diff] [blame] | 289 | .orderby(pe.posting_date, pe.name, order=Order.desc) |
Gursheen Anand | d5aa0e3 | 2023-07-11 14:47:23 +0530 | [diff] [blame] | 290 | ) |
Deepesh Garg | 92e503f | 2023-08-29 20:45:57 +0530 | [diff] [blame] | 291 | query = apply_common_conditions(filters, query, doctype="Payment Entry", payments=True) |
Gursheen Anand | f5027fd | 2023-07-12 16:42:58 +0530 | [diff] [blame] | 292 | payment_entries = query.run(as_dict=True) |
Gursheen Anand | 6c11ca1 | 2023-07-12 14:43:18 +0530 | [diff] [blame] | 293 | return payment_entries |
Gursheen Kaur Anand | 1094319 | 2023-07-12 11:00:35 +0530 | [diff] [blame] | 294 | |
| 295 | |
Deepesh Garg | 92e503f | 2023-08-29 20:45:57 +0530 | [diff] [blame] | 296 | def apply_common_conditions(filters, query, doctype, child_doctype=None, payments=False): |
Gursheen Anand | 33f8f7d | 2023-07-21 10:57:55 +0530 | [diff] [blame] | 297 | parent_doc = frappe.qb.DocType(doctype) |
| 298 | if child_doctype: |
| 299 | child_doc = frappe.qb.DocType(child_doctype) |
Sagar Vora | 30e4052 | 2023-07-04 17:41:30 +0530 | [diff] [blame] | 300 | |
Deepesh Garg | 92e503f | 2023-08-29 20:45:57 +0530 | [diff] [blame] | 301 | join_required = False |
Sagar Vora | 30e4052 | 2023-07-04 17:41:30 +0530 | [diff] [blame] | 302 | |
Gursheen Anand | 6c11ca1 | 2023-07-12 14:43:18 +0530 | [diff] [blame] | 303 | if filters.get("company"): |
| 304 | query = query.where(parent_doc.company == filters.company) |
| 305 | if filters.get("from_date"): |
| 306 | query = query.where(parent_doc.posting_date >= filters.from_date) |
| 307 | if filters.get("to_date"): |
| 308 | query = query.where(parent_doc.posting_date <= filters.to_date) |
Sagar Vora | 30e4052 | 2023-07-04 17:41:30 +0530 | [diff] [blame] | 309 | |
Gursheen Anand | 6c11ca1 | 2023-07-12 14:43:18 +0530 | [diff] [blame] | 310 | if payments: |
| 311 | if filters.get("cost_center"): |
| 312 | query = query.where(parent_doc.cost_center == filters.cost_center) |
| 313 | else: |
| 314 | if filters.get("cost_center"): |
| 315 | query = query.where(child_doc.cost_center == filters.cost_center) |
Deepesh Garg | 92e503f | 2023-08-29 20:45:57 +0530 | [diff] [blame] | 316 | join_required = True |
Gursheen Anand | 6c11ca1 | 2023-07-12 14:43:18 +0530 | [diff] [blame] | 317 | if filters.get("warehouse"): |
| 318 | query = query.where(child_doc.warehouse == filters.warehouse) |
Deepesh Garg | 92e503f | 2023-08-29 20:45:57 +0530 | [diff] [blame] | 319 | join_required = True |
Gursheen Anand | 6c11ca1 | 2023-07-12 14:43:18 +0530 | [diff] [blame] | 320 | if filters.get("item_group"): |
| 321 | query = query.where(child_doc.item_group == filters.item_group) |
Deepesh Garg | 92e503f | 2023-08-29 20:45:57 +0530 | [diff] [blame] | 322 | join_required = True |
| 323 | |
| 324 | if not payments: |
| 325 | if filters.get("brand"): |
| 326 | query = query.where(child_doc.brand == filters.brand) |
| 327 | join_required = True |
| 328 | |
| 329 | if join_required: |
| 330 | query = query.inner_join(child_doc).on(parent_doc.name == child_doc.parent) |
| 331 | query = query.distinct() |
Gursheen Anand | c084fe6 | 2023-07-14 11:05:50 +0530 | [diff] [blame] | 332 | |
| 333 | if parent_doc.get_table_name() != "tabJournal Entry": |
| 334 | query = filter_invoices_based_on_dimensions(filters, query, parent_doc) |
Deepesh Garg | 92e503f | 2023-08-29 20:45:57 +0530 | [diff] [blame] | 335 | |
Gursheen Anand | 6c11ca1 | 2023-07-12 14:43:18 +0530 | [diff] [blame] | 336 | return query |
Gursheen Anand | f5027fd | 2023-07-12 16:42:58 +0530 | [diff] [blame] | 337 | |
| 338 | |
| 339 | def get_advance_taxes_and_charges(invoice_list): |
| 340 | adv_taxes = frappe.qb.DocType("Advance Taxes and Charges") |
| 341 | return ( |
| 342 | frappe.qb.from_(adv_taxes) |
| 343 | .select( |
| 344 | adv_taxes.parent, |
| 345 | adv_taxes.account_head, |
| 346 | ( |
| 347 | frappe.qb.terms.Case() |
| 348 | .when(adv_taxes.add_deduct_tax == "Add", Sum(adv_taxes.base_tax_amount)) |
| 349 | .else_(Sum(adv_taxes.base_tax_amount) * -1) |
| 350 | ).as_("tax_amount"), |
| 351 | ) |
| 352 | .where( |
| 353 | (adv_taxes.parent.isin([inv.name for inv in invoice_list])) |
| 354 | & (adv_taxes.charge_type.isin(["On Paid Amount", "Actual"])) |
| 355 | & (adv_taxes.base_tax_amount != 0) |
| 356 | ) |
| 357 | .groupby(adv_taxes.parent, adv_taxes.account_head, adv_taxes.add_deduct_tax) |
Gursheen Anand | bf08aa7 | 2023-07-12 17:17:58 +0530 | [diff] [blame] | 358 | ).run(as_dict=True) |
| 359 | |
| 360 | |
Gursheen Anand | c084fe6 | 2023-07-14 11:05:50 +0530 | [diff] [blame] | 361 | def filter_invoices_based_on_dimensions(filters, query, parent_doc): |
| 362 | accounting_dimensions = get_accounting_dimensions(as_list=False) |
| 363 | if accounting_dimensions: |
Gursheen Anand | bf08aa7 | 2023-07-12 17:17:58 +0530 | [diff] [blame] | 364 | for dimension in accounting_dimensions: |
| 365 | if filters.get(dimension.fieldname): |
| 366 | if frappe.get_cached_value("DocType", dimension.document_type, "is_tree"): |
| 367 | filters[dimension.fieldname] = get_dimension_with_children( |
| 368 | dimension.document_type, filters.get(dimension.fieldname) |
| 369 | ) |
| 370 | fieldname = dimension.fieldname |
ruthra kumar | 7b3f938 | 2024-01-11 16:24:43 +0530 | [diff] [blame^] | 371 | query = query.where(parent_doc[fieldname].isin(filters[fieldname])) |
Gursheen Anand | c084fe6 | 2023-07-14 11:05:50 +0530 | [diff] [blame] | 372 | return query |
Gursheen Anand | 944244c | 2023-07-14 10:50:12 +0530 | [diff] [blame] | 373 | |
| 374 | |
| 375 | def get_opening_row(party_type, party, from_date, company): |
| 376 | party_account = get_party_account(party_type, party, company, include_advance=True) |
| 377 | gle = frappe.qb.DocType("GL Entry") |
| 378 | return ( |
| 379 | frappe.qb.from_(gle) |
| 380 | .select( |
| 381 | ConstantColumn("Opening").as_("account"), |
| 382 | Sum(gle.debit).as_("debit"), |
| 383 | Sum(gle.credit).as_("credit"), |
| 384 | (Sum(gle.debit) - Sum(gle.credit)).as_("balance"), |
| 385 | ) |
Gursheen Anand | 33f8f7d | 2023-07-21 10:57:55 +0530 | [diff] [blame] | 386 | .where( |
| 387 | (gle.account.isin(party_account)) |
| 388 | & (gle.party == party) |
| 389 | & (gle.posting_date < from_date) |
Gursheen Anand | 59a2a04 | 2023-07-21 13:22:01 +0530 | [diff] [blame] | 390 | & (gle.is_cancelled == 0) |
Gursheen Anand | 33f8f7d | 2023-07-21 10:57:55 +0530 | [diff] [blame] | 391 | ) |
Gursheen Anand | 944244c | 2023-07-14 10:50:12 +0530 | [diff] [blame] | 392 | ).run(as_dict=True) |