Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 1 | import frappe |
| 2 | from frappe import _ |
Nabin Hait | 0a90ce5 | 2019-03-28 19:43:02 +0530 | [diff] [blame] | 3 | from frappe.email import sendmail_to_system_managers |
Chillar Anand | 915b343 | 2021-09-02 16:44:59 +0530 | [diff] [blame] | 4 | from frappe.utils import ( |
| 5 | add_days, |
| 6 | add_months, |
| 7 | cint, |
| 8 | date_diff, |
| 9 | flt, |
| 10 | get_first_day, |
| 11 | get_last_day, |
| 12 | get_link_to_form, |
| 13 | getdate, |
| 14 | rounded, |
| 15 | today, |
| 16 | ) |
| 17 | |
| 18 | from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( |
| 19 | get_accounting_dimensions, |
| 20 | ) |
| 21 | from erpnext.accounts.utils import get_account_currency |
| 22 | |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 23 | |
| 24 | def validate_service_stop_date(doc): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 25 | """Validates service_stop_date for Purchase Invoice and Sales Invoice""" |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 26 | |
Akhil Narang | 3effaf2 | 2024-03-27 11:37:26 +0530 | [diff] [blame] | 27 | enable_check = "enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense" |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 28 | |
| 29 | old_stop_dates = {} |
Akhil Narang | 3effaf2 | 2024-03-27 11:37:26 +0530 | [diff] [blame] | 30 | old_doc = frappe.db.get_all(f"{doc.doctype} Item", {"parent": doc.name}, ["name", "service_stop_date"]) |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 31 | |
| 32 | for d in old_doc: |
| 33 | old_stop_dates[d.name] = d.service_stop_date or "" |
| 34 | |
| 35 | for item in doc.items: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 36 | if not item.get(enable_check): |
| 37 | continue |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 38 | |
| 39 | if item.service_stop_date: |
| 40 | if date_diff(item.service_stop_date, item.service_start_date) < 0: |
| 41 | frappe.throw(_("Service Stop Date cannot be before Service Start Date")) |
| 42 | |
| 43 | if date_diff(item.service_stop_date, item.service_end_date) > 0: |
| 44 | frappe.throw(_("Service Stop Date cannot be after Service End Date")) |
| 45 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 46 | if ( |
| 47 | old_stop_dates |
| 48 | and old_stop_dates.get(item.name) |
| 49 | and item.service_stop_date != old_stop_dates.get(item.name) |
| 50 | ): |
Suraj Shetty | 48e9bc3 | 2020-01-29 15:06:18 +0530 | [diff] [blame] | 51 | frappe.throw(_("Cannot change Service Stop Date for item in row {0}").format(item.idx)) |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 52 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 53 | |
Mangesh-Khairnar | 2f7861a | 2020-05-02 20:09:33 +0530 | [diff] [blame] | 54 | def build_conditions(process_type, account, company): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 55 | conditions = "" |
| 56 | deferred_account = ( |
| 57 | "item.deferred_revenue_account" if process_type == "Income" else "item.deferred_expense_account" |
| 58 | ) |
Mangesh-Khairnar | 2f7861a | 2020-05-02 20:09:33 +0530 | [diff] [blame] | 59 | |
| 60 | if account: |
Akhil Narang | 3effaf2 | 2024-03-27 11:37:26 +0530 | [diff] [blame] | 61 | conditions += f"AND {deferred_account}='{account}'" |
Mangesh-Khairnar | 2f7861a | 2020-05-02 20:09:33 +0530 | [diff] [blame] | 62 | elif company: |
Ankush Menat | f3b3d81 | 2021-05-17 16:43:38 +0530 | [diff] [blame] | 63 | conditions += f"AND p.company = {frappe.db.escape(company)}" |
Mangesh-Khairnar | 2f7861a | 2020-05-02 20:09:33 +0530 | [diff] [blame] | 64 | |
| 65 | return conditions |
| 66 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 67 | |
Akhil Narang | 3effaf2 | 2024-03-27 11:37:26 +0530 | [diff] [blame] | 68 | def convert_deferred_expense_to_expense(deferred_process, start_date=None, end_date=None, conditions=""): |
Nabin Hait | 0a90ce5 | 2019-03-28 19:43:02 +0530 | [diff] [blame] | 69 | # book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM |
Mangesh-Khairnar | 2f7861a | 2020-05-02 20:09:33 +0530 | [diff] [blame] | 70 | |
Nabin Hait | 0a90ce5 | 2019-03-28 19:43:02 +0530 | [diff] [blame] | 71 | if not start_date: |
| 72 | start_date = add_months(today(), -1) |
| 73 | if not end_date: |
| 74 | end_date = add_days(today(), -1) |
| 75 | |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 76 | # check for the purchase invoice for which GL entries has to be done |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 77 | invoices = frappe.db.sql_list( |
Akhil Narang | 3effaf2 | 2024-03-27 11:37:26 +0530 | [diff] [blame] | 78 | f""" |
Mangesh-Khairnar | 2f7861a | 2020-05-02 20:09:33 +0530 | [diff] [blame] | 79 | select distinct item.parent |
| 80 | from `tabPurchase Invoice Item` item, `tabPurchase Invoice` p |
| 81 | where item.service_start_date<=%s and item.service_end_date>=%s |
| 82 | and item.enable_deferred_expense = 1 and item.parent=p.name |
| 83 | and item.docstatus = 1 and ifnull(item.amount, 0) > 0 |
Akhil Narang | 3effaf2 | 2024-03-27 11:37:26 +0530 | [diff] [blame] | 84 | {conditions} |
| 85 | """, |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 86 | (end_date, start_date), |
| 87 | ) # nosec |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 88 | |
| 89 | # For each invoice, book deferred expense |
| 90 | for invoice in invoices: |
| 91 | doc = frappe.get_doc("Purchase Invoice", invoice) |
Mangesh-Khairnar | 2f7861a | 2020-05-02 20:09:33 +0530 | [diff] [blame] | 92 | book_deferred_income_or_expense(doc, deferred_process, end_date) |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 93 | |
Mangesh-Khairnar | 2f7861a | 2020-05-02 20:09:33 +0530 | [diff] [blame] | 94 | if frappe.flags.deferred_accounting_error: |
| 95 | send_mail(deferred_process) |
| 96 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 97 | |
Akhil Narang | 3effaf2 | 2024-03-27 11:37:26 +0530 | [diff] [blame] | 98 | def convert_deferred_revenue_to_income(deferred_process, start_date=None, end_date=None, conditions=""): |
Nabin Hait | 0a90ce5 | 2019-03-28 19:43:02 +0530 | [diff] [blame] | 99 | # book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM |
Mangesh-Khairnar | 2f7861a | 2020-05-02 20:09:33 +0530 | [diff] [blame] | 100 | |
Nabin Hait | 0a90ce5 | 2019-03-28 19:43:02 +0530 | [diff] [blame] | 101 | if not start_date: |
| 102 | start_date = add_months(today(), -1) |
| 103 | if not end_date: |
| 104 | end_date = add_days(today(), -1) |
| 105 | |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 106 | # check for the sales invoice for which GL entries has to be done |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 107 | invoices = frappe.db.sql_list( |
Akhil Narang | 3effaf2 | 2024-03-27 11:37:26 +0530 | [diff] [blame] | 108 | f""" |
Mangesh-Khairnar | 2f7861a | 2020-05-02 20:09:33 +0530 | [diff] [blame] | 109 | select distinct item.parent |
| 110 | from `tabSales Invoice Item` item, `tabSales Invoice` p |
| 111 | where item.service_start_date<=%s and item.service_end_date>=%s |
| 112 | and item.enable_deferred_revenue = 1 and item.parent=p.name |
| 113 | and item.docstatus = 1 and ifnull(item.amount, 0) > 0 |
Akhil Narang | 3effaf2 | 2024-03-27 11:37:26 +0530 | [diff] [blame] | 114 | {conditions} |
| 115 | """, |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 116 | (end_date, start_date), |
| 117 | ) # nosec |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 118 | |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 119 | for invoice in invoices: |
| 120 | doc = frappe.get_doc("Sales Invoice", invoice) |
Mangesh-Khairnar | 2f7861a | 2020-05-02 20:09:33 +0530 | [diff] [blame] | 121 | book_deferred_income_or_expense(doc, deferred_process, end_date) |
| 122 | |
| 123 | if frappe.flags.deferred_accounting_error: |
| 124 | send_mail(deferred_process) |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 125 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 126 | |
Gursheen Kaur Anand | 674af15 | 2023-07-09 20:41:12 +0530 | [diff] [blame] | 127 | def get_booking_dates(doc, item, posting_date=None, prev_posting_date=None): |
Nabin Hait | 0a90ce5 | 2019-03-28 19:43:02 +0530 | [diff] [blame] | 128 | if not posting_date: |
| 129 | posting_date = add_days(today(), -1) |
| 130 | |
| 131 | last_gl_entry = False |
| 132 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 133 | deferred_account = ( |
| 134 | "deferred_revenue_account" if doc.doctype == "Sales Invoice" else "deferred_expense_account" |
| 135 | ) |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 136 | |
Gursheen Kaur Anand | 674af15 | 2023-07-09 20:41:12 +0530 | [diff] [blame] | 137 | if not prev_posting_date: |
| 138 | prev_gl_entry = frappe.db.sql( |
| 139 | """ |
| 140 | select name, posting_date from `tabGL Entry` where company=%s and account=%s and |
| 141 | voucher_type=%s and voucher_no=%s and voucher_detail_no=%s |
| 142 | and is_cancelled = 0 |
| 143 | order by posting_date desc limit 1 |
| 144 | """, |
| 145 | (doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), |
| 146 | as_dict=True, |
| 147 | ) |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 148 | |
Gursheen Kaur Anand | 674af15 | 2023-07-09 20:41:12 +0530 | [diff] [blame] | 149 | prev_gl_via_je = frappe.db.sql( |
| 150 | """ |
| 151 | SELECT p.name, p.posting_date FROM `tabJournal Entry` p, `tabJournal Entry Account` c |
| 152 | WHERE p.name = c.parent and p.company=%s and c.account=%s |
| 153 | and c.reference_type=%s and c.reference_name=%s |
| 154 | and c.reference_detail_no=%s and c.docstatus < 2 order by posting_date desc limit 1 |
| 155 | """, |
| 156 | (doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), |
| 157 | as_dict=True, |
| 158 | ) |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 159 | |
Gursheen Kaur Anand | 674af15 | 2023-07-09 20:41:12 +0530 | [diff] [blame] | 160 | if prev_gl_via_je: |
| 161 | if (not prev_gl_entry) or ( |
| 162 | prev_gl_entry and prev_gl_entry[0].posting_date < prev_gl_via_je[0].posting_date |
| 163 | ): |
| 164 | prev_gl_entry = prev_gl_via_je |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 165 | |
Gursheen Kaur Anand | 674af15 | 2023-07-09 20:41:12 +0530 | [diff] [blame] | 166 | if prev_gl_entry: |
| 167 | start_date = getdate(add_days(prev_gl_entry[0].posting_date, 1)) |
| 168 | else: |
| 169 | start_date = item.service_start_date |
| 170 | |
Nabin Hait | 0a90ce5 | 2019-03-28 19:43:02 +0530 | [diff] [blame] | 171 | else: |
Gursheen Kaur Anand | 674af15 | 2023-07-09 20:41:12 +0530 | [diff] [blame] | 172 | start_date = getdate(add_days(prev_posting_date, 1)) |
Nabin Hait | 0a90ce5 | 2019-03-28 19:43:02 +0530 | [diff] [blame] | 173 | end_date = get_last_day(start_date) |
| 174 | if end_date >= item.service_end_date: |
| 175 | end_date = item.service_end_date |
| 176 | last_gl_entry = True |
Nabin Hait | 66d07c2 | 2019-03-29 13:25:11 +0530 | [diff] [blame] | 177 | elif item.service_stop_date and end_date >= item.service_stop_date: |
| 178 | end_date = item.service_stop_date |
| 179 | last_gl_entry = True |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 180 | |
Nabin Hait | 0a90ce5 | 2019-03-28 19:43:02 +0530 | [diff] [blame] | 181 | if end_date > getdate(posting_date): |
| 182 | end_date = posting_date |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 183 | |
Nabin Hait | 0a90ce5 | 2019-03-28 19:43:02 +0530 | [diff] [blame] | 184 | if getdate(start_date) <= getdate(end_date): |
| 185 | return start_date, end_date, last_gl_entry |
| 186 | else: |
| 187 | return None, None, None |
| 188 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 189 | |
| 190 | def calculate_monthly_amount( |
| 191 | doc, item, last_gl_entry, start_date, end_date, total_days, total_booking_days, account_currency |
| 192 | ): |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 193 | amount, base_amount = 0, 0 |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 194 | |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 195 | if not last_gl_entry: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 196 | total_months = ( |
| 197 | (item.service_end_date.year - item.service_start_date.year) * 12 |
| 198 | + (item.service_end_date.month - item.service_start_date.month) |
| 199 | + 1 |
| 200 | ) |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 201 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 202 | prorate_factor = flt(date_diff(item.service_end_date, item.service_start_date)) / flt( |
| 203 | date_diff(get_last_day(item.service_end_date), get_first_day(item.service_start_date)) |
| 204 | ) |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 205 | |
| 206 | actual_months = rounded(total_months * prorate_factor, 1) |
| 207 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 208 | already_booked_amount, already_booked_amount_in_account_currency = get_already_booked_amount( |
| 209 | doc, item |
| 210 | ) |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 211 | base_amount = flt(item.base_net_amount / actual_months, item.precision("base_net_amount")) |
| 212 | |
| 213 | if base_amount + already_booked_amount > item.base_net_amount: |
| 214 | base_amount = item.base_net_amount - already_booked_amount |
| 215 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 216 | if account_currency == doc.company_currency: |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 217 | amount = base_amount |
| 218 | else: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 219 | amount = flt(item.net_amount / actual_months, item.precision("net_amount")) |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 220 | if amount + already_booked_amount_in_account_currency > item.net_amount: |
| 221 | amount = item.net_amount - already_booked_amount_in_account_currency |
| 222 | |
barredterra | eb9ee3f | 2023-12-05 11:22:55 +0100 | [diff] [blame] | 223 | if get_first_day(start_date) != start_date or get_last_day(end_date) != end_date: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 224 | partial_month = flt(date_diff(end_date, start_date)) / flt( |
| 225 | date_diff(get_last_day(end_date), get_first_day(start_date)) |
| 226 | ) |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 227 | |
| 228 | base_amount = rounded(partial_month, 1) * base_amount |
| 229 | amount = rounded(partial_month, 1) * amount |
| 230 | else: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 231 | already_booked_amount, already_booked_amount_in_account_currency = get_already_booked_amount( |
| 232 | doc, item |
| 233 | ) |
Akhil Narang | 3effaf2 | 2024-03-27 11:37:26 +0530 | [diff] [blame] | 234 | base_amount = flt(item.base_net_amount - already_booked_amount, item.precision("base_net_amount")) |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 235 | if account_currency == doc.company_currency: |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 236 | amount = base_amount |
| 237 | else: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 238 | amount = flt( |
| 239 | item.net_amount - already_booked_amount_in_account_currency, item.precision("net_amount") |
| 240 | ) |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 241 | |
| 242 | return amount, base_amount |
| 243 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 244 | |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 245 | def calculate_amount(doc, item, last_gl_entry, total_days, total_booking_days, account_currency): |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 246 | amount, base_amount = 0, 0 |
| 247 | if not last_gl_entry: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 248 | base_amount = flt( |
| 249 | item.base_net_amount * total_booking_days / flt(total_days), item.precision("base_net_amount") |
| 250 | ) |
| 251 | if account_currency == doc.company_currency: |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 252 | amount = base_amount |
| 253 | else: |
Akhil Narang | 3effaf2 | 2024-03-27 11:37:26 +0530 | [diff] [blame] | 254 | amount = flt(item.net_amount * total_booking_days / flt(total_days), item.precision("net_amount")) |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 255 | else: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 256 | already_booked_amount, already_booked_amount_in_account_currency = get_already_booked_amount( |
| 257 | doc, item |
| 258 | ) |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 259 | |
Akhil Narang | 3effaf2 | 2024-03-27 11:37:26 +0530 | [diff] [blame] | 260 | base_amount = flt(item.base_net_amount - already_booked_amount, item.precision("base_net_amount")) |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 261 | if account_currency == doc.company_currency: |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 262 | amount = base_amount |
| 263 | else: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 264 | amount = flt( |
| 265 | item.net_amount - already_booked_amount_in_account_currency, item.precision("net_amount") |
| 266 | ) |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 267 | |
| 268 | return amount, base_amount |
| 269 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 270 | |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 271 | def get_already_booked_amount(doc, item): |
| 272 | if doc.doctype == "Sales Invoice": |
| 273 | total_credit_debit, total_credit_debit_currency = "debit", "debit_in_account_currency" |
| 274 | deferred_account = "deferred_revenue_account" |
| 275 | else: |
| 276 | total_credit_debit, total_credit_debit_currency = "credit", "credit_in_account_currency" |
| 277 | deferred_account = "deferred_expense_account" |
| 278 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 279 | gl_entries_details = frappe.db.sql( |
| 280 | """ |
Akhil Narang | 3effaf2 | 2024-03-27 11:37:26 +0530 | [diff] [blame] | 281 | select sum({}) as total_credit, sum({}) as total_credit_in_account_currency, voucher_detail_no |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 282 | from `tabGL Entry` where company=%s and account=%s and voucher_type=%s and voucher_no=%s and voucher_detail_no=%s |
Deepesh Garg | 366120f | 2022-03-01 11:56:20 +0530 | [diff] [blame] | 283 | and is_cancelled = 0 |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 284 | group by voucher_detail_no |
Akhil Narang | 3effaf2 | 2024-03-27 11:37:26 +0530 | [diff] [blame] | 285 | """.format(total_credit_debit, total_credit_debit_currency), |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 286 | (doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), |
| 287 | as_dict=True, |
| 288 | ) |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 289 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 290 | journal_entry_details = frappe.db.sql( |
| 291 | """ |
Akhil Narang | 3effaf2 | 2024-03-27 11:37:26 +0530 | [diff] [blame] | 292 | SELECT sum(c.{}) as total_credit, sum(c.{}) as total_credit_in_account_currency, reference_detail_no |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 293 | FROM `tabJournal Entry` p , `tabJournal Entry Account` c WHERE p.name = c.parent and |
| 294 | p.company = %s and c.account=%s and c.reference_type=%s and c.reference_name=%s and c.reference_detail_no=%s |
| 295 | and p.docstatus < 2 group by reference_detail_no |
Akhil Narang | 3effaf2 | 2024-03-27 11:37:26 +0530 | [diff] [blame] | 296 | """.format(total_credit_debit, total_credit_debit_currency), |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 297 | (doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), |
| 298 | as_dict=True, |
| 299 | ) |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 300 | |
| 301 | already_booked_amount = gl_entries_details[0].total_credit if gl_entries_details else 0 |
| 302 | already_booked_amount += journal_entry_details[0].total_credit if journal_entry_details else 0 |
| 303 | |
| 304 | if doc.currency == doc.company_currency: |
| 305 | already_booked_amount_in_account_currency = already_booked_amount |
| 306 | else: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 307 | already_booked_amount_in_account_currency = ( |
| 308 | gl_entries_details[0].total_credit_in_account_currency if gl_entries_details else 0 |
| 309 | ) |
| 310 | already_booked_amount_in_account_currency += ( |
| 311 | journal_entry_details[0].total_credit_in_account_currency if journal_entry_details else 0 |
| 312 | ) |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 313 | |
| 314 | return already_booked_amount, already_booked_amount_in_account_currency |
| 315 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 316 | |
Mangesh-Khairnar | 2f7861a | 2020-05-02 20:09:33 +0530 | [diff] [blame] | 317 | def book_deferred_income_or_expense(doc, deferred_process, posting_date=None): |
Akhil Narang | 3effaf2 | 2024-03-27 11:37:26 +0530 | [diff] [blame] | 318 | enable_check = "enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense" |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 319 | |
ruthra kumar | ba15810 | 2023-08-01 07:58:09 +0530 | [diff] [blame] | 320 | accounts_frozen_upto = frappe.db.get_single_value("Accounts Settings", "acc_frozen_upto") |
Deepesh Garg | 30a647f | 2022-01-07 19:52:38 +0530 | [diff] [blame] | 321 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 322 | def _book_deferred_revenue_or_expense( |
Gursheen Kaur Anand | 674af15 | 2023-07-09 20:41:12 +0530 | [diff] [blame] | 323 | item, |
| 324 | via_journal_entry, |
| 325 | submit_journal_entry, |
| 326 | book_deferred_entries_based_on, |
| 327 | prev_posting_date=None, |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 328 | ): |
Gursheen Kaur Anand | 674af15 | 2023-07-09 20:41:12 +0530 | [diff] [blame] | 329 | start_date, end_date, last_gl_entry = get_booking_dates( |
| 330 | doc, item, posting_date=posting_date, prev_posting_date=prev_posting_date |
| 331 | ) |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 332 | if not (start_date and end_date): |
| 333 | return |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 334 | |
Deepesh Garg | 98f294a | 2022-01-03 19:40:47 +0530 | [diff] [blame] | 335 | account_currency = get_account_currency(item.expense_account or item.income_account) |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 336 | if doc.doctype == "Sales Invoice": |
| 337 | against, project = doc.customer, doc.project |
| 338 | credit_account, debit_account = item.income_account, item.deferred_revenue_account |
| 339 | else: |
| 340 | against, project = doc.supplier, item.project |
| 341 | credit_account, debit_account = item.deferred_expense_account, item.expense_account |
| 342 | |
Nabin Hait | 0a90ce5 | 2019-03-28 19:43:02 +0530 | [diff] [blame] | 343 | total_days = date_diff(item.service_end_date, item.service_start_date) + 1 |
| 344 | total_booking_days = date_diff(end_date, start_date) + 1 |
| 345 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 346 | if book_deferred_entries_based_on == "Months": |
| 347 | amount, base_amount = calculate_monthly_amount( |
| 348 | doc, |
| 349 | item, |
| 350 | last_gl_entry, |
| 351 | start_date, |
| 352 | end_date, |
| 353 | total_days, |
| 354 | total_booking_days, |
| 355 | account_currency, |
| 356 | ) |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 357 | else: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 358 | amount, base_amount = calculate_amount( |
| 359 | doc, item, last_gl_entry, total_days, total_booking_days, account_currency |
| 360 | ) |
Nabin Hait | 0a90ce5 | 2019-03-28 19:43:02 +0530 | [diff] [blame] | 361 | |
Deepesh Garg | f79a72d | 2021-06-24 14:14:46 +0530 | [diff] [blame] | 362 | if not amount: |
| 363 | return |
| 364 | |
Gursheen Kaur Anand | 674af15 | 2023-07-09 20:41:12 +0530 | [diff] [blame] | 365 | gl_posting_date = end_date |
| 366 | prev_posting_date = None |
Deepesh Garg | 30a647f | 2022-01-07 19:52:38 +0530 | [diff] [blame] | 367 | # check if books nor frozen till endate: |
Deepesh Garg | a3ab8f9 | 2023-01-03 17:51:41 +0530 | [diff] [blame] | 368 | if accounts_frozen_upto and getdate(end_date) <= getdate(accounts_frozen_upto): |
Gursheen Kaur Anand | 674af15 | 2023-07-09 20:41:12 +0530 | [diff] [blame] | 369 | gl_posting_date = get_last_day(add_days(accounts_frozen_upto, 1)) |
| 370 | prev_posting_date = end_date |
Deepesh Garg | 30a647f | 2022-01-07 19:52:38 +0530 | [diff] [blame] | 371 | |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 372 | if via_journal_entry: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 373 | book_revenue_via_journal_entry( |
| 374 | doc, |
| 375 | credit_account, |
| 376 | debit_account, |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 377 | amount, |
| 378 | base_amount, |
Gursheen Kaur Anand | 674af15 | 2023-07-09 20:41:12 +0530 | [diff] [blame] | 379 | gl_posting_date, |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 380 | project, |
| 381 | account_currency, |
| 382 | item.cost_center, |
| 383 | item, |
| 384 | deferred_process, |
| 385 | submit_journal_entry, |
| 386 | ) |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 387 | else: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 388 | make_gl_entries( |
| 389 | doc, |
| 390 | credit_account, |
| 391 | debit_account, |
| 392 | against, |
| 393 | amount, |
| 394 | base_amount, |
Gursheen Kaur Anand | 674af15 | 2023-07-09 20:41:12 +0530 | [diff] [blame] | 395 | gl_posting_date, |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 396 | project, |
| 397 | account_currency, |
| 398 | item.cost_center, |
| 399 | item, |
| 400 | deferred_process, |
| 401 | ) |
Mangesh-Khairnar | 2f7861a | 2020-05-02 20:09:33 +0530 | [diff] [blame] | 402 | |
| 403 | # Returned in case of any errors because it tries to submit the same record again and again in case of errors |
| 404 | if frappe.flags.deferred_accounting_error: |
| 405 | return |
Nabin Hait | 0a90ce5 | 2019-03-28 19:43:02 +0530 | [diff] [blame] | 406 | |
| 407 | if getdate(end_date) < getdate(posting_date) and not last_gl_entry: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 408 | _book_deferred_revenue_or_expense( |
Gursheen Kaur Anand | 674af15 | 2023-07-09 20:41:12 +0530 | [diff] [blame] | 409 | item, |
| 410 | via_journal_entry, |
| 411 | submit_journal_entry, |
| 412 | book_deferred_entries_based_on, |
| 413 | prev_posting_date, |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 414 | ) |
Nabin Hait | 0a90ce5 | 2019-03-28 19:43:02 +0530 | [diff] [blame] | 415 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 416 | via_journal_entry = cint( |
| 417 | frappe.db.get_singles_value("Accounts Settings", "book_deferred_entries_via_journal_entry") |
| 418 | ) |
Akhil Narang | 3effaf2 | 2024-03-27 11:37:26 +0530 | [diff] [blame] | 419 | submit_journal_entry = cint(frappe.db.get_singles_value("Accounts Settings", "submit_journal_entries")) |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 420 | book_deferred_entries_based_on = frappe.db.get_singles_value( |
| 421 | "Accounts Settings", "book_deferred_entries_based_on" |
| 422 | ) |
Nabin Hait | 0a90ce5 | 2019-03-28 19:43:02 +0530 | [diff] [blame] | 423 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 424 | for item in doc.get("items"): |
Nabin Hait | 0a90ce5 | 2019-03-28 19:43:02 +0530 | [diff] [blame] | 425 | if item.get(enable_check): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 426 | _book_deferred_revenue_or_expense( |
| 427 | item, via_journal_entry, submit_journal_entry, book_deferred_entries_based_on |
| 428 | ) |
| 429 | |
Nabin Hait | 0a90ce5 | 2019-03-28 19:43:02 +0530 | [diff] [blame] | 430 | |
Chinmay D. Pai | 0d147b0 | 2020-05-24 00:54:04 +0530 | [diff] [blame] | 431 | def process_deferred_accounting(posting_date=None): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 432 | """Converts deferred income/expense into income/expense |
| 433 | Executed via background jobs on every month end""" |
Mangesh-Khairnar | 2f7861a | 2020-05-02 20:09:33 +0530 | [diff] [blame] | 434 | |
Chinmay D. Pai | 0d147b0 | 2020-05-24 00:54:04 +0530 | [diff] [blame] | 435 | if not posting_date: |
| 436 | posting_date = today() |
| 437 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 438 | if not cint( |
Akhil Narang | 3effaf2 | 2024-03-27 11:37:26 +0530 | [diff] [blame] | 439 | frappe.db.get_singles_value("Accounts Settings", "automatically_process_deferred_accounting_entry") |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 440 | ): |
Mangesh-Khairnar | 2f7861a | 2020-05-02 20:09:33 +0530 | [diff] [blame] | 441 | return |
| 442 | |
| 443 | start_date = add_months(today(), -1) |
| 444 | end_date = add_days(today(), -1) |
| 445 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 446 | companies = frappe.get_all("Company") |
Mangesh-Khairnar | 2f7861a | 2020-05-02 20:09:33 +0530 | [diff] [blame] | 447 | |
Deepesh Garg | 5069095 | 2021-07-01 09:31:31 +0530 | [diff] [blame] | 448 | for company in companies: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 449 | for record_type in ("Income", "Expense"): |
| 450 | doc = frappe.get_doc( |
| 451 | dict( |
| 452 | doctype="Process Deferred Accounting", |
| 453 | company=company.name, |
| 454 | posting_date=posting_date, |
| 455 | start_date=start_date, |
| 456 | end_date=end_date, |
| 457 | type=record_type, |
| 458 | ) |
| 459 | ) |
Deepesh Garg | 5069095 | 2021-07-01 09:31:31 +0530 | [diff] [blame] | 460 | |
| 461 | doc.insert() |
| 462 | doc.submit() |
Mangesh-Khairnar | 2f7861a | 2020-05-02 20:09:33 +0530 | [diff] [blame] | 463 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 464 | |
| 465 | def make_gl_entries( |
| 466 | doc, |
| 467 | credit_account, |
| 468 | debit_account, |
| 469 | against, |
| 470 | amount, |
| 471 | base_amount, |
| 472 | posting_date, |
| 473 | project, |
| 474 | account_currency, |
| 475 | cost_center, |
| 476 | item, |
| 477 | deferred_process=None, |
| 478 | ): |
Nabin Hait | 0a90ce5 | 2019-03-28 19:43:02 +0530 | [diff] [blame] | 479 | # GL Entry for crediting the amount in the deferred expense |
| 480 | from erpnext.accounts.general_ledger import make_gl_entries |
| 481 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 482 | if amount == 0: |
| 483 | return |
rohitwaghchaure | e123ec6 | 2019-11-06 15:25:00 +0530 | [diff] [blame] | 484 | |
Nabin Hait | 0a90ce5 | 2019-03-28 19:43:02 +0530 | [diff] [blame] | 485 | gl_entries = [] |
| 486 | gl_entries.append( |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 487 | doc.get_gl_dict( |
| 488 | { |
| 489 | "account": credit_account, |
| 490 | "against": against, |
| 491 | "credit": base_amount, |
| 492 | "credit_in_account_currency": amount, |
| 493 | "cost_center": cost_center, |
| 494 | "voucher_detail_no": item.name, |
| 495 | "posting_date": posting_date, |
| 496 | "project": project, |
| 497 | "against_voucher_type": "Process Deferred Accounting", |
| 498 | "against_voucher": deferred_process, |
| 499 | }, |
| 500 | account_currency, |
| 501 | item=item, |
| 502 | ) |
Nabin Hait | 0a90ce5 | 2019-03-28 19:43:02 +0530 | [diff] [blame] | 503 | ) |
| 504 | # GL Entry to debit the amount from the expense |
| 505 | gl_entries.append( |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 506 | doc.get_gl_dict( |
| 507 | { |
| 508 | "account": debit_account, |
| 509 | "against": against, |
| 510 | "debit": base_amount, |
| 511 | "debit_in_account_currency": amount, |
| 512 | "cost_center": cost_center, |
| 513 | "voucher_detail_no": item.name, |
| 514 | "posting_date": posting_date, |
| 515 | "project": project, |
| 516 | "against_voucher_type": "Process Deferred Accounting", |
| 517 | "against_voucher": deferred_process, |
| 518 | }, |
| 519 | account_currency, |
| 520 | item=item, |
| 521 | ) |
Nabin Hait | 0a90ce5 | 2019-03-28 19:43:02 +0530 | [diff] [blame] | 522 | ) |
| 523 | |
Zarrar | e83ff38 | 2018-09-21 15:45:40 +0530 | [diff] [blame] | 524 | if gl_entries: |
Nabin Hait | 29fcb14 | 2019-02-13 17:18:12 +0530 | [diff] [blame] | 525 | try: |
| 526 | make_gl_entries(gl_entries, cancel=(doc.docstatus == 2), merge_entries=True) |
| 527 | frappe.db.commit() |
Deepesh Garg | f1a669c | 2021-09-29 22:26:33 +0530 | [diff] [blame] | 528 | except Exception as e: |
| 529 | if frappe.flags.in_test: |
Rushabh Mehta | 548afba | 2022-05-02 15:04:26 +0530 | [diff] [blame] | 530 | doc.log_error(f"Error while processing deferred accounting for Invoice {doc.name}") |
Deepesh Garg | 3c64e20 | 2021-12-04 20:05:37 +0530 | [diff] [blame] | 531 | raise e |
Deepesh Garg | f1a669c | 2021-09-29 22:26:33 +0530 | [diff] [blame] | 532 | else: |
| 533 | frappe.db.rollback() |
Rushabh Mehta | 548afba | 2022-05-02 15:04:26 +0530 | [diff] [blame] | 534 | doc.log_error(f"Error while processing deferred accounting for Invoice {doc.name}") |
Deepesh Garg | f1a669c | 2021-09-29 22:26:33 +0530 | [diff] [blame] | 535 | frappe.flags.deferred_accounting_error = True |
Mangesh-Khairnar | 2f7861a | 2020-05-02 20:09:33 +0530 | [diff] [blame] | 536 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 537 | |
Mangesh-Khairnar | 2f7861a | 2020-05-02 20:09:33 +0530 | [diff] [blame] | 538 | def send_mail(deferred_process): |
Ankush Menat | b6783b1 | 2021-05-17 17:06:12 +0530 | [diff] [blame] | 539 | title = _("Error while processing deferred accounting for {0}").format(deferred_process) |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 540 | link = get_link_to_form("Process Deferred Accounting", deferred_process) |
Ankush Menat | b6783b1 | 2021-05-17 17:06:12 +0530 | [diff] [blame] | 541 | content = _("Deferred accounting failed for some invoices:") + "\n" |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 542 | content += _( |
| 543 | "Please check Process Deferred Accounting {0} and submit manually after resolving errors." |
| 544 | ).format(link) |
Mangesh-Khairnar | 2f7861a | 2020-05-02 20:09:33 +0530 | [diff] [blame] | 545 | sendmail_to_system_managers(title, content) |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 546 | |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 547 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 548 | def book_revenue_via_journal_entry( |
| 549 | doc, |
| 550 | credit_account, |
| 551 | debit_account, |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 552 | amount, |
| 553 | base_amount, |
| 554 | posting_date, |
| 555 | project, |
| 556 | account_currency, |
| 557 | cost_center, |
| 558 | item, |
| 559 | deferred_process=None, |
| 560 | submit="No", |
| 561 | ): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 562 | if amount == 0: |
| 563 | return |
| 564 | |
| 565 | journal_entry = frappe.new_doc("Journal Entry") |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 566 | journal_entry.posting_date = posting_date |
| 567 | journal_entry.company = doc.company |
Akhil Narang | 3effaf2 | 2024-03-27 11:37:26 +0530 | [diff] [blame] | 568 | journal_entry.voucher_type = "Deferred Revenue" if doc.doctype == "Sales Invoice" else "Deferred Expense" |
Deepesh Garg | 9bf5f76 | 2022-04-06 17:33:46 +0530 | [diff] [blame] | 569 | journal_entry.process_deferred_accounting = deferred_process |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 570 | |
| 571 | debit_entry = { |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 572 | "account": credit_account, |
| 573 | "credit": base_amount, |
| 574 | "credit_in_account_currency": amount, |
| 575 | "account_currency": account_currency, |
| 576 | "reference_name": doc.name, |
| 577 | "reference_type": doc.doctype, |
| 578 | "reference_detail_no": item.name, |
| 579 | "cost_center": cost_center, |
| 580 | "project": project, |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 581 | } |
| 582 | |
| 583 | credit_entry = { |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 584 | "account": debit_account, |
| 585 | "debit": base_amount, |
| 586 | "debit_in_account_currency": amount, |
| 587 | "account_currency": account_currency, |
| 588 | "reference_name": doc.name, |
| 589 | "reference_type": doc.doctype, |
| 590 | "reference_detail_no": item.name, |
| 591 | "cost_center": cost_center, |
| 592 | "project": project, |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 593 | } |
| 594 | |
| 595 | for dimension in get_accounting_dimensions(): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 596 | debit_entry.update({dimension: item.get(dimension)}) |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 597 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 598 | credit_entry.update({dimension: item.get(dimension)}) |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 599 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 600 | journal_entry.append("accounts", debit_entry) |
| 601 | journal_entry.append("accounts", credit_entry) |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 602 | |
| 603 | try: |
| 604 | journal_entry.save() |
| 605 | |
| 606 | if submit: |
| 607 | journal_entry.submit() |
Deepesh Garg | 0ba4fce | 2021-12-04 19:25:44 +0530 | [diff] [blame] | 608 | |
| 609 | frappe.db.commit() |
Ankush Menat | 694ae81 | 2021-09-01 14:40:56 +0530 | [diff] [blame] | 610 | except Exception: |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 611 | frappe.db.rollback() |
Rushabh Mehta | 548afba | 2022-05-02 15:04:26 +0530 | [diff] [blame] | 612 | doc.log_error(f"Error while processing deferred accounting for Invoice {doc.name}") |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 613 | frappe.flags.deferred_accounting_error = True |
| 614 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 615 | |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 616 | def get_deferred_booking_accounts(doctype, voucher_detail_no, dr_or_cr): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 617 | if doctype == "Sales Invoice": |
| 618 | credit_account, debit_account = frappe.db.get_value( |
| 619 | "Sales Invoice Item", |
| 620 | {"name": voucher_detail_no}, |
| 621 | ["income_account", "deferred_revenue_account"], |
| 622 | ) |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 623 | else: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 624 | credit_account, debit_account = frappe.db.get_value( |
| 625 | "Purchase Invoice Item", |
| 626 | {"name": voucher_detail_no}, |
| 627 | ["deferred_expense_account", "expense_account"], |
| 628 | ) |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 629 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 630 | if dr_or_cr == "Debit": |
Deepesh Garg | 7cc1cf3 | 2020-06-23 09:57:56 +0530 | [diff] [blame] | 631 | return debit_account |
| 632 | else: |
| 633 | return credit_account |