From 218e7774238908cc7f26c38243a5322bfe585bee Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Wed, 11 Dec 2024 17:57:47 +0530 Subject: [PATCH 01/50] fix: better indicator base amount for Tax Witholding in Journal Entry (cherry picked from commit 56a0a0db18fb16ce4a30a92a0fc271351def3894) --- .../tax_withholding_details/tax_withholding_details.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py index 0c18dac77682..b969627fdd65 100644 --- a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py +++ b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py @@ -72,8 +72,8 @@ def get_result(filters, tds_docs, tds_accounts, tax_category_map, journal_entry_ if net_total_map.get((voucher_type, name)): if voucher_type == "Journal Entry": # back calcalute total amount from rate and tax_amount - if rate: - total_amount = grand_total = base_total = tax_amount / (rate / 100) + base_total = min(tax_amount / (rate / 100), net_total_map.get((voucher_type, name))[0]) + total_amount = grand_total = base_total elif voucher_type == "Purchase Invoice": total_amount, grand_total, base_total, bill_no, bill_date = net_total_map.get( (voucher_type, name) @@ -405,7 +405,7 @@ def get_doc_info(vouchers, doctype, tax_category_map, net_total_map=None): "paid_amount_after_tax", "base_paid_amount", ], - "Journal Entry": ["total_amount"], + "Journal Entry": ["total_debit"], } entries = frappe.get_all( @@ -427,7 +427,7 @@ def get_doc_info(vouchers, doctype, tax_category_map, net_total_map=None): elif doctype == "Payment Entry": value = [entry.paid_amount, entry.paid_amount_after_tax, entry.base_paid_amount] else: - value = [entry.total_amount] * 3 + value = [entry.total_debit] * 3 net_total_map[(doctype, entry.name)] = value From 75aee42635f87c6a608b43ca7c11d56071965f07 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 18 Dec 2024 10:54:21 +0530 Subject: [PATCH 02/50] fix: use utility method to generate url (cherry picked from commit b970eb8b1507813b5c13bce6be4a9a10eb1769db) --- .../doctype/plaid_settings/plaid_settings.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.js b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.js index fc3bf804245f..3c72f2cbab5f 100644 --- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.js +++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.js @@ -25,7 +25,12 @@ frappe.ui.form.on("Plaid Settings", { method: "erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.enqueue_synchronization", freeze: true, callback: () => { - let bank_transaction_link = 'Bank Transaction'; + let bank_transaction_link = frappe.utils.get_form_link( + "Bank Transaction", + "", + true, + "Bank Transaction" + ); frappe.msgprint({ title: __("Sync Started"), From 8b810f5fb8f451ec6f3c29dd2070785750a643d5 Mon Sep 17 00:00:00 2001 From: ljain112 Date: Wed, 18 Dec 2024 13:47:37 +0530 Subject: [PATCH 03/50] fix: 'str' object has no attribute 'get_sql' (cherry picked from commit 9a43acb65c3930cfd552d25e6aa3f3909bb4adf9) --- erpnext/accounts/report/financial_statements.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py index 918bafa169af..c653ae1b38fa 100644 --- a/erpnext/accounts/report/financial_statements.py +++ b/erpnext/accounts/report/financial_statements.py @@ -529,13 +529,12 @@ def get_accounting_entries( from frappe.desk.reportview import build_match_conditions + query, params = query.walk() match_conditions = build_match_conditions(doctype) if match_conditions: query += "and" + match_conditions - query, params = query.walk() - return frappe.db.sql(query, params, as_dict=True) From 0fd7792f49f97b45d620098e0faa433a3ea904f1 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 18 Dec 2024 17:28:22 +0530 Subject: [PATCH 04/50] fix: added docs.frappe.io in documentation_url (#44776) (cherry picked from commit febdf4c61e0a2b748aa11c23c8e83dcfc6089599) --- .github/helper/documentation.py | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/helper/documentation.py b/.github/helper/documentation.py index 83346045f89d..d07c880684ea 100644 --- a/.github/helper/documentation.py +++ b/.github/helper/documentation.py @@ -10,6 +10,7 @@ DOCUMENTATION_DOMAINS = [ "docs.erpnext.com", + "docs.frappe.io", "frappeframework.com", ] From 20324224d37e1554fcb958ee79b94e5257ac93c5 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 18 Dec 2024 20:38:56 +0530 Subject: [PATCH 05/50] fix: POS Closing entry issue (backport #44772) (#44781) fix: POS Closing entry issue (#44772) (cherry picked from commit 779dd2d7984fa091094da59a4fc310efccb22e81) Co-authored-by: rohitwaghchaure --- .../pos_invoice_merge_log.py | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py index 761ed8d804ee..18136a033b01 100644 --- a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py +++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py @@ -117,11 +117,13 @@ def on_submit(self): sales = [d for d in pos_invoice_docs if d.get("is_return") == 0] sales_invoice, credit_note = "", "" + sales_invoice_doc = None if sales: - sales_invoice = self.process_merging_into_sales_invoice(sales) + sales_invoice_doc = self.process_merging_into_sales_invoice(sales) + sales_invoice = sales_invoice_doc.name if returns: - credit_note = self.process_merging_into_credit_note(returns, sales_invoice) + credit_note = self.process_merging_into_credit_note(returns, sales_invoice_doc) self.save() # save consolidated_sales_invoice & consolidated_credit_note ref in merge log self.update_pos_invoices(pos_invoice_docs, sales_invoice, credit_note) @@ -152,15 +154,23 @@ def process_merging_into_sales_invoice(self, data): self.consolidated_invoice = sales_invoice.name - return sales_invoice.name + return sales_invoice - def process_merging_into_credit_note(self, data, sales_invoice): + def process_merging_into_credit_note(self, data, sales_invoice_doc=None): credit_note = self.get_new_sales_invoice() credit_note.is_return = 1 credit_note = self.merge_pos_invoice_into(credit_note, data) + referenes = {} + + if sales_invoice_doc: + credit_note.return_against = sales_invoice_doc.name + + for d in sales_invoice_doc.items: + referenes[d.item_code] = d.name - credit_note.return_against = sales_invoice + for d in credit_note.items: + d.sales_invoice_item = referenes.get(d.item_code) credit_note.is_consolidated = 1 credit_note.set_posting_time = 1 @@ -366,7 +376,12 @@ def get_serial_and_batch_bundles(self): return [] def cancel_linked_invoices(self): - for si_name in [self.consolidated_invoice, self.consolidated_credit_note]: + invoices = [self.consolidated_invoice, self.consolidated_credit_note] + if not invoices: + return + + invoices.reverse() + for si_name in invoices: if not si_name: continue si = frappe.get_doc("Sales Invoice", si_name) From b706a8274f489f1d0b9ef160d771ecd38abadaf8 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 13:31:28 +0530 Subject: [PATCH 06/50] perf: SABB (backport #44764) (#44789) perf: SABB (#44764) (cherry picked from commit 90baa38f643811d2edd3b26b8cb81ae62ad158c5) Co-authored-by: rohitwaghchaure --- erpnext/controllers/stock_controller.py | 5 +++- .../serial_and_batch_bundle.py | 12 ++++----- erpnext/stock/serial_batch_bundle.py | 16 +++--------- erpnext/stock/stock_ledger.py | 25 +++++++++++-------- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 8f0a5d5edf52..c1cb83657da9 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -1758,6 +1758,9 @@ def make_bundle_for_material_transfer(**kwargs): bundle_doc.calculate_qty_and_amount() bundle_doc.flags.ignore_permissions = True bundle_doc.flags.ignore_validate = True - bundle_doc.save(ignore_permissions=True) + if kwargs.do_not_submit: + bundle_doc.save(ignore_permissions=True) + else: + bundle_doc.submit() return bundle_doc.name diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index f96a6760bec0..6ff0317dce60 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -90,12 +90,10 @@ def validate(self): self.validate_duplicate_serial_and_batch_no() self.validate_voucher_no() - if self.docstatus == 0: - self.allow_existing_serial_nos() - if self.type_of_transaction == "Maintenance": return + self.allow_existing_serial_nos() if not self.flags.ignore_validate_serial_batch or frappe.flags.in_test: self.validate_serial_nos_duplicate() self.check_future_entries_exists() @@ -2101,6 +2099,8 @@ def update_available_batches(available_batches, *reserved_batches) -> None: def get_available_batches(kwargs): + from erpnext.stock.utils import get_combine_datetime + stock_ledger_entry = frappe.qb.DocType("Stock Ledger Entry") batch_ledger = frappe.qb.DocType("Serial and Batch Entry") batch_table = frappe.qb.DocType("Batch") @@ -2128,9 +2128,9 @@ def get_available_batches(kwargs): if kwargs.get("posting_time") is None: kwargs.posting_time = nowtime() - timestamp_condition = CombineDatetime( - stock_ledger_entry.posting_date, stock_ledger_entry.posting_time - ) <= CombineDatetime(kwargs.posting_date, kwargs.posting_time) + timestamp_condition = stock_ledger_entry.posting_datetime <= get_combine_datetime( + kwargs.posting_date, kwargs.posting_time + ) query = query.where(timestamp_condition) diff --git a/erpnext/stock/serial_batch_bundle.py b/erpnext/stock/serial_batch_bundle.py index 05b3536c57ba..732a14c2fb5b 100644 --- a/erpnext/stock/serial_batch_bundle.py +++ b/erpnext/stock/serial_batch_bundle.py @@ -725,15 +725,6 @@ def set_stock_value_difference(self): stock_value_change = self.batch_avg_rate[batch_no] * ledger.qty self.stock_value_change += stock_value_change - frappe.db.set_value( - "Serial and Batch Entry", - ledger.name, - { - "stock_value_difference": stock_value_change, - "incoming_rate": self.batch_avg_rate[batch_no], - }, - ) - def calculate_valuation_rate(self): if not hasattr(self, "wh_data"): return @@ -947,12 +938,13 @@ def make_serial_and_batch_bundle(self): if self.get("make_bundle_from_sle") and self.type_of_transaction == "Inward": doc.flags.ignore_validate_serial_batch = True - doc.save() - self.validate_qty(doc) - if not hasattr(self, "do_not_submit") or not self.do_not_submit: doc.flags.ignore_voucher_validation = True doc.submit() + else: + doc.save() + + self.validate_qty(doc) return doc diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index 26e7af150b9c..1e1b24115696 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -988,18 +988,23 @@ def calculate_valuation_for_serial_batch_bundle(self, sle): if not frappe.db.exists("Serial and Batch Bundle", sle.serial_and_batch_bundle): return - doc = frappe.get_cached_doc("Serial and Batch Bundle", sle.serial_and_batch_bundle) - - doc.set_incoming_rate(save=True, allow_negative_stock=self.allow_negative_stock) - doc.calculate_qty_and_amount(save=True) + if self.args.get("sle_id") and sle.actual_qty < 0: + doc = frappe.db.get_value( + "Serial and Batch Bundle", + sle.serial_and_batch_bundle, + ["total_amount", "total_qty"], + as_dict=1, + ) + else: + doc = frappe.get_doc("Serial and Batch Bundle", sle.serial_and_batch_bundle) + doc.set_incoming_rate(save=True, allow_negative_stock=self.allow_negative_stock) + doc.calculate_qty_and_amount(save=True) self.wh_data.stock_value = round_off_if_near_zero(self.wh_data.stock_value + doc.total_amount) - - precision = doc.precision("total_qty") - self.wh_data.qty_after_transaction += flt(doc.total_qty, precision) - if flt(self.wh_data.qty_after_transaction, precision): - self.wh_data.valuation_rate = flt(self.wh_data.stock_value, precision) / flt( - self.wh_data.qty_after_transaction, precision + self.wh_data.qty_after_transaction += flt(doc.total_qty, self.flt_precision) + if flt(self.wh_data.qty_after_transaction, self.flt_precision): + self.wh_data.valuation_rate = flt(self.wh_data.stock_value, self.flt_precision) / flt( + self.wh_data.qty_after_transaction, self.flt_precision ) def update_valuation_rate_in_serial_and_batch_bundle(self, sle, valuation_rate): From cdeec8d24c29cb4de3159234a6e627d2f9e7593a Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 20 Dec 2024 09:35:51 +0530 Subject: [PATCH 07/50] fix: closing stock balance permissions (backport #44791) (#44793) * fix: closing stock balance permissions (#44791) (cherry picked from commit 3662a6a41d2e1e4631c964dffa4d215542a38af1) # Conflicts: # erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.json * chore: fix conflicts --------- Co-authored-by: rohitwaghchaure --- .../closing_stock_balance.json | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.json b/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.json index acb96e7a2f5f..c1e5878a4391 100644 --- a/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.json +++ b/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.json @@ -113,7 +113,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2023-05-18 11:46:04.448220", + "modified": "2024-12-19 13:48:46.618066", "modified_by": "Administrator", "module": "Stock", "name": "Closing Stock Balance", @@ -121,6 +121,7 @@ "owner": "Administrator", "permissions": [ { + "cancel": 1, "create": 1, "delete": 1, "email": 1, @@ -130,10 +131,39 @@ "report": 1, "role": "System Manager", "share": 1, + "submit": 1, + "write": 1 + }, + { + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Stock Manager", + "share": 1, + "submit": 1, + "write": 1 + }, + { + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Stock User", + "share": 1, + "submit": 1, "write": 1 } ], "sort_field": "modified", "sort_order": "DESC", "states": [] -} \ No newline at end of file +} From db9a319104f2b1988a99e6f45bf555e1dcd79ca1 Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Fri, 20 Dec 2024 11:02:33 +0530 Subject: [PATCH 08/50] fix: typerror on TDS payable monthly report (backport #37707) --- .../report/tax_withholding_details/tax_withholding_details.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py index b969627fdd65..d6e0af0b5da8 100644 --- a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py +++ b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py @@ -70,7 +70,7 @@ def get_result(filters, tds_docs, tds_accounts, tax_category_map, journal_entry_ rate = tax_rate_map.get(tax_withholding_category) if net_total_map.get((voucher_type, name)): - if voucher_type == "Journal Entry": + if voucher_type == "Journal Entry" and tax_amount and rate: # back calcalute total amount from rate and tax_amount base_total = min(tax_amount / (rate / 100), net_total_map.get((voucher_type, name))[0]) total_amount = grand_total = base_total From 98cc79d9420b63773a1bf04db702d31a162a968c Mon Sep 17 00:00:00 2001 From: mahsem <137205921+mahsem@users.noreply.github.com> Date: Wed, 11 Dec 2024 16:32:04 +0100 Subject: [PATCH 09/50] feat: swedish COA (cherry picked from commit 8a5f7ec4d7079045f8af1ef8fcfffe10f473220d) --- ...ontoplan_BAS_2024_with_account_number.json | 6300 +++++++++++++++++ 1 file changed, 6300 insertions(+) create mode 100644 erpnext/accounts/doctype/account/chart_of_accounts/verified/se_kontoplan_BAS_2024_with_account_number.json diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/se_kontoplan_BAS_2024_with_account_number.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/se_kontoplan_BAS_2024_with_account_number.json new file mode 100644 index 000000000000..6411c04aad6f --- /dev/null +++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/se_kontoplan_BAS_2024_with_account_number.json @@ -0,0 +1,6300 @@ +{ + "country_code": "se", + "name": "BAS 2024 med Nummer", + "tree": { + "1 Tillgångar": { + "root_type": "Asset", + "account_type": "Fixed Asset", + "is_group": 1, + "10 Immateriella anläggningstillgångar": { + "is_group": 1, + "101 Utvecklingsutgifter": { + "is_group": 1, + "Utvecklingsutgifter": { + "account_number": "1010" + }, + "Balanserade utgifter för forskning och utveckling": { + "account_number": "1011" + }, + "Balanserade utgifter för programvaror": { + "account_number": "1012" + }, + "Ackumulerade nedskrivningar på balanserade utgifter": { + "account_number": "1018", + "account_type": "Accumulated Depreciation" + }, + "Ackumulerade avskrivningar på balanserade utgifter": { + "account_number": "1019", + "account_type": "Accumulated Depreciation" + } + }, + "102 Koncessioner m.m.": { + "is_group": 1, + "Koncessioner m.m.": { + "account_number": "1020" + }, + "Ackumulerade nedskrivningar på koncessioner m.m.": { + "account_number": "1028", + "account_type": "Accumulated Depreciation" + }, + "Ackumulerade avskrivningar på koncessioner m.m.": { + "account_number": "1029", + "account_type": "Accumulated Depreciation" + } + }, + "103 Patent": { + "is_group": 1, + "Patent": { + "account_number": "1030", + "account_type": "Fixed Asset" + }, + "Ackumulerade nedskrivningar på patent": { + "account_number": "1038" + }, + "Ackumulerade avskrivningar på patent": { + "account_number": "1039", + "account_type": "Accumulated Depreciation" + } + }, + "104 Licenser": { + "is_group": 1, + "Licenser": { + "account_number": "1040" + }, + "Ackumulerade nedskrivningar på licenser": { + "account_number": "1048" + }, + "Ackumulerade avskrivningar på licenser": { + "account_number": "1049", + "account_type": "Accumulated Depreciation" + } + }, + "105 Varumärken": { + "is_group": 1, + "Varumärken": { + "account_number": "1050" + }, + "Ackumulerade nedskrivningar på varumärken": { + "account_number": "1058" + }, + "Ackumulerade avskrivningar på varumärken": { + "account_number": "1059", + "account_type": "Accumulated Depreciation" + } + }, + "106 Hyresrätter, tomträtter och liknande": { + "is_group": 1, + "Hyresrätter, tomträtter och liknande": { + "account_number": "1060", + "account_type": "Fixed Asset" + }, + "Ackumulerade nedskrivningar på hyresrätter, tomträtter och liknande": { + "account_number": "1068" + }, + "Ackumulerade avskrivningar på hyresrätter, tomträtter och liknande": { + "account_number": "1069", + "account_type": "Accumulated Depreciation" + } + }, + "107 Goodwill": { + "is_group": 1, + "Goodwill": { + "account_number": "1070" + }, + "Ackumulerade nedskrivningar på goodwill": { + "account_number": "1078" + }, + "Ackumulerade avskrivningar på goodwill": { + "account_number": "1079", + "account_type": "Accumulated Depreciation" + } + }, + "108 Förskott för immateriella anläggningstillgångar": { + "is_group": 1, + "Förskott för immateriell anläggningstillgång": { + "account_number": "1080" + }, + "Pågående projekt för immateriella anläggningstillgångar": { + "account_number": "1081" + }, + "Förskott för immateriella anläggningstillgångar": { + "account_number": "1088" + } + } + }, + "11 Byggnader och mark": { + "is_group": 1, + "111 Byggnader": { + "is_group": 1, + "Byggnader": { + "account_number": "1110", + "account_type": "Fixed Asset" + }, + "Byggnader på egen mark": { + "account_number": "1111" + }, + "Byggnader på annans mark": { + "account_number": "1112" + }, + "Ackumulerade nedskrivningar på byggnader": { + "account_number": "1118", + "account_type": "Accumulated Depreciation" + }, + "Ackumulerade avskrivningar på byggnader": { + "account_number": "1119", + "account_type": "Accumulated Depreciation" + } + }, + "112 Förbättringsutgifter på annans fastighet": { + "is_group": 1, + "Förbättringsutgifter på annans fastighet": { + "account_number": "1120" + }, + "Ackumulerade avskrivningar på förbättringsutgifter på annans fastighet": { + "account_number": "1129", + "account_type": "Accumulated Depreciation" + } + }, + "113 Mark": { + "is_group": 1, + "Mark": { + "account_number": "1130", + "account_type": "Fixed Asset" + } + }, + "114 Tomter och obebyggda markområden": { + "is_group": 1, + "Tomter och obebyggda markområden": { + "account_number": "1140" + } + }, + "115 Markanläggningar": { + "is_group": 1, + "Markanläggningar": { + "account_number": "1150", + "account_type": "Fixed Asset" + }, + "Ackumulerade nedskrivningar på markanläggningar": { + "account_number": "1158" + }, + "Ackumulerade avskrivningar på markanläggningar": { + "account_number": "1159", + "account_type": "Accumulated Depreciation" + } + }, + "118 Pågående nyanläggningar och förskott för byggnader och mark": { + "is_group": 1, + "Pågående nyanläggningar och förskott för byggnader och mark": { + "account_number": "1180", + "account_type": "Fixed Asset" + }, + "Pågående ny-, till- och ombyggnad": { + "account_number": "1181" + }, + "Förskott för byggnader och mark": { + "account_number": "1188", + "account_type": "Accumulated Depreciation" + } + } + }, + "12 Maskiner och inventarier": { + "is_group": 1, + "121 Maskiner och andra tekniska anläggningar": { + "is_group": 1, + "Maskiner och andra tekniska anläggningar": { + "account_number": "1210", + "account_type": "Fixed Asset" + }, + "Maskiner": { + "account_number": "1211", + "account_type": "Fixed Asset" + }, + "Andra tekniska anläggningar": { + "account_number": "1213", + "account_type": "Fixed Asset" + }, + "Ackumulerade nedskrivningar på maskiner och andra tekniska anläggningar": { + "account_number": "1218", + "account_type": "Accumulated Depreciation" + }, + "Ackumulerade avskrivningar på maskiner och andra tekniska anläggningar": { + "account_number": "1219", + "account_type": "Accumulated Depreciation" + } + }, + "122 Inventarier och verktyg": { + "is_group": 1, + "Inventarier och verktyg": { + "account_number": "1220", + "account_type": "Fixed Asset" + }, + "Inventarier": { + "account_number": "1221" + }, + "Byggnadsinventarier": { + "account_number": "1222" + }, + "Verktyg": { + "account_number": "1225" + }, + "Ackumulerade nedskrivningar på inventarier och verktyg": { + "account_number": "1228" + }, + "Ackumulerade avskrivningar på inventarier och verktyg": { + "account_number": "1229", + "account_type": "Accumulated Depreciation" + } + }, + "123 Installationer": { + "is_group": 1, + "Installationer": { + "account_number": "1230", + "account_type": "Fixed Asset" + }, + "Installationer på egen fastighet": { + "account_number": "1231", + "account_type": "Fixed Asset" + }, + "Installationer på annans fastighet": { + "account_number": "1232", + "account_type": "Fixed Asset" + }, + "Ackumulerade nedskrivningar på installationer": { + "account_number": "1238", + "account_type": "Accumulated Depreciation" + }, + "Ackumulerade avskrivningar på installationer": { + "account_number": "1239", + "account_type": "Accumulated Depreciation" + } + }, + "124 Bilar och andra transportmedel": { + "is_group": 1, + "Bilar och andra transportmedel": { + "account_number": "1240", + "account_type": "Fixed Asset" + }, + "Personbilar": { + "account_number": "1241", + "account_type": "Fixed Asset" + }, + "Lastbilar": { + "account_number": "1242", + "account_type": "Fixed Asset" + }, + "Truckar": { + "account_number": "1243", + "account_type": "Fixed Asset" + }, + "Arbetsmaskiner": { + "account_number": "1244", + "account_type": "Fixed Asset" + }, + "Traktorer": { + "account_number": "1245", + "account_type": "Fixed Asset" + }, + "Motorcyklar, mopeder och skotrar": { + "account_number": "1246", + "account_type": "Fixed Asset" + }, + "Båtar, flygplan och helikoptrar": { + "account_number": "1247", + "account_type": "Fixed Asset" + }, + "Ackumulerade nedskrivningar på bilar och andra transportmedel": { + "account_number": "1248", + "account_type": "Fixed Asset" + }, + "Ackumulerade avskrivningar på bilar och andra transportmedel": { + "account_number": "1249", + "account_type": "Accumulated Depreciation" + } + }, + "125 Datorer": { + "is_group": 1, + "Datorer": { + "account_number": "1250", + "account_type": "Fixed Asset" + }, + "Datorer, företaget": { + "account_number": "1251" + }, + "Datorer, personal": { + "account_number": "1257" + }, + "Ackumulerade nedskrivningar på datorer": { + "account_number": "1258", + "account_type": "Accumulated Depreciation" + }, + "Ackumulerade avskrivningar på datorer": { + "account_number": "1259", + "account_type": "Accumulated Depreciation" + } + }, + "126 Leasade tillgångar": { + "is_group": 1, + "Leasade tillgångar": { + "account_number": "1260" + }, + "Ackumulerade avskrivningar på leasade tillgångar": { + "account_number": "1269", + "account_type": "Accumulated Depreciation" + } + }, + "128 Pågående nyanläggningar och förskott för maskiner och inventarier": { + "is_group": 1, + "Pågående nyanläggningar och förskott för maskiner och inventarier": { + "account_number": "1280" + }, + "Pågående nyanläggningar, maskiner och inventarier": { + "account_number": "1281" + }, + "Förskott för maskiner och inventarier": { + "account_number": "1288" + } + }, + "129 Övriga materiella anläggningstillgångar": { + "is_group": 1, + "Övriga materiella anläggningstillgångar": { + "account_number": "1290", + "account_type": "Fixed Asset" + }, + "Konst och liknande tillgångar": { + "account_number": "1291", + "account_type": "Fixed Asset" + }, + "Djur som klassificeras som anläggningstillgång": { + "account_number": "1292" + }, + "Ackumulerade nedskrivningar på övriga materiella anläggningstillgångar": { + "account_number": "1298" + }, + "Ackumulerade avskrivningar på övriga materiella anläggningstillgångar": { + "account_number": "1299", + "account_type": "Accumulated Depreciation" + } + } + }, + "13 Finansiella anläggningstillgångar": { + "is_group": 1, + "131 Andelar i koncernföretag": { + "is_group": 1, + "Andelar i koncernföretag": { + "account_number": "1310" + }, + "Aktier i noterade svenska koncernföretag": { + "account_number": "1311" + }, + "Aktier i onoterade svenska koncernföretag": { + "account_number": "1312" + }, + "Aktier i noterade utländska koncernföretag": { + "account_number": "1313" + }, + "Aktier i onoterade utländska koncernföretag": { + "account_number": "1314" + }, + "Andra andelar i svenska koncernföretag": { + "account_number": "1316" + }, + "Andra andelar i utländska koncernföretag": { + "account_number": "1317" + }, + "Ackumulerade nedskrivningar av andelar i koncernföretag": { + "account_number": "1318" + } + }, + "132 Långfristiga fordringar hos koncernföretag": { + "is_group": 1, + "Långfristiga fordringar hos koncernföretag": { + "account_number": "1320" + }, + "Långfristiga fordringar hos moderföretag": { + "account_number": "1321" + }, + "Långfristiga fordringar hos dotterföretag": { + "account_number": "1322" + }, + "Långfristiga fordringar hosandra koncernföretag": { + "account_number": "1323" + }, + "Ackumulerade nedskrivningar av långfristiga fordringar hos koncernföretag": { + "account_number": "1328" + } + }, + "133 Andelar i intresseföretag, gemensamt styrda företag och övriga företag": { + "is_group": 1, + "Andelar i intresseföretag, gemensamt styrda företag och övriga företag": { + "account_number": "1330" + }, + "Andelar i intresseföretag": { + "account_number": "1331" + }, + "Ackumulerade nedskrivningar av andelar i intresseföretag": { + "account_number": "1332" + }, + "Andelar i gemensamt styrda företag": { + "account_number": "1333" + }, + "Ackumulerade nedskrivningar av andelar i gemensamt styrda företag": { + "account_number": "1334" + }, + "Andelar i övriga företag som det finns ett ägarintresse i": { + "account_number": "1336" + }, + "Ackumulerade nedskrivningar av andelar i övriga företag": { + "account_number": "1337" + }, + "Ackumulerade nedskrivningar av andelar i intresseföretag övriga": { + "account_number": "1338" + } + }, + "134 Långfristiga fordringar hos intresseföretag": { + "is_group": 1, + "Långfristiga fordringar hos intresseföretag, gemensamt styrda företag": { + "account_number": "1340" + }, + "Långfristiga fordringar hos intresseföretag": { + "account_number": "1341" + }, + "Ackumulerade nedskrivningar av långfristiga fordringar hos intresseföretag": { + "account_number": "1342" + }, + "Långfristiga fordringar hos gemensamt styrda företag": { + "account_number": "1343" + }, + "Ackumulerade nedskrivningar av långfristiga fordringar hos gemensamt styrda företag": { + "account_number": "1344" + }, + "Långfristiga fordringar hos övriga företag som det finns ett ägarintresse i": { + "account_number": "1346" + }, + "Ackumulerade nedskrivningar av långfristiga fordringar hos övriga företag": { + "account_number": "1347" + }, + "Ackumulerade nedskrivningar av långfristiga fordringar hos intresseföretag, gemensamt styrda företag": { + "account_number": "1348" + } + }, + "135 Andelar och värdepapper i andra företag": { + "is_group": 1, + "Andelar och värdepapper i andra företag": { + "account_number": "1350" + }, + "Andelar i noterade företag": { + "account_number": "1351" + }, + "Andra andelar": { + "account_number": "1352" + }, + "Andelar i bostadsrättsföreningar": { + "account_number": "1353" + }, + "Obligationer": { + "account_number": "1354" + }, + "Andelar i ekonomiska föreningar, övriga företag": { + "account_number": "1356" + }, + "Andelar i handelsbolag, andra företag": { + "account_number": "1357" + }, + "Ackumulerade nedskrivningar av andra andelar och värdepapper": { + "account_number": "1358" + } + }, + "136 Lån till delägare eller närstående enligt ABL, långfristig del": { + "is_group": 1, + "Lån till delägare eller närstående enligt ABL, långfristig del": { + "account_number": "1360" + }, + "Ackumulerade nedskrivningar av lån till delägare eller närstående enligt ABL, långfristig del": { + "account_number": "1369" + } + }, + "137 Uppskjuten skattefordran": { + "is_group": 1, + "Uppskjuten skattefordran": { + "account_number": "1370" + } + }, + "138 Andra långfristiga fordringar": { + "is_group": 1, + "Andra långfristiga fordringar": { + "account_number": "1380", + "account_type": "Receivable" + }, + "Långfristiga reversfordringar": { + "account_number": "1381" + }, + "Långfristiga fordringar hos anställda": { + "account_number": "1382" + }, + "Lämnade depositioner, långfristiga": { + "account_number": "1383" + }, + "Derivat": { + "account_number": "1384" + }, + "Kapitalförsäkring": { + "account_number": "1385" + }, + "Långfristiga kontraktsfordringar": { + "account_number": "1387" + }, + "Långfristiga kundfordringar": { + "account_number": "1388" + }, + "Ackumulerade nedskrivningar av andra långfristiga fordringar": { + "account_number": "1389" + } + } + }, + "14 Lager, produkter i arbete och pågående arbeten": { + "is_group": 1, + "account_type": "Stock", + "141 Lager av råvaror": { + "is_group": 1, + "Lager av råvaror": { + "account_number": "1410", + "account_type": "Stock" + }, + "Förändring av lager av råvaror": { + "account_number": "1419", + "account_type": "Stock Adjustment" + } + }, + "142 Lager av tillsatsmaterial och förnödenheter": { + "is_group": 1, + "Lager av tillsatsmaterial och förnödenheter": { + "account_number": "1420", + "account_type": "Stock" + }, + "Förändring av lager av tillsatsmaterial och förnödenheter": { + "account_number": "1429", + "account_type": "Stock Adjustment" + } + }, + "144 Produkter i arbete": { + "is_group": 1, + "Produkter i arbete": { + "account_number": "1440", + "account_type": "Stock" + }, + "Förändring av produkter i arbete": { + "account_number": "1449", + "account_type": "Stock Adjustment" + } + }, + "145 Lager av färdiga varor": { + "is_group": 1, + "Lager av färdiga varor": { + "account_number": "1450", + "account_type": "Stock" + }, + "Förändring av lager av färdiga varor": { + "account_number": "1459", + "account_type": "Stock Adjustment" + } + }, + "146 Lager av handelsvaror": { + "is_group": 1, + "Lager av handelsvaror": { + "account_number": "1460", + "account_type": "Stock" + }, + "Lager av varor VMB": { + "account_number": "1465" + }, + "Lager av varor VMB förenklad": { + "account_number": "1467" + }, + "Förändring av lager av handelsvaror": { + "account_number": "1469", + "account_type": "Stock Adjustment" + } + }, + "147 Pågående arbeten": { + "is_group": 1, + "Pågående arbeten": { + "account_number": "1470" + }, + "Pågående arbeten, nedlagda kostnader": { + "account_number": "1471" + }, + "Pågående arbeten, fakturering": { + "account_number": "1478" + }, + "Förändring av pågående arbeten": { + "account_number": "1479" + } + }, + "148 Förskott för varor och tjänster": { + "is_group": 1, + "Förskott för varor och tjänster": { + "account_number": "1480" + }, + "Remburser": { + "account_number": "1481" + }, + "Övriga förskott till leverantörer": { + "account_number": "1489" + } + }, + "149 Övriga lagertillgångar": { + "is_group": 1, + "Övriga lagertillgångar": { + "account_number": "1490" + }, + "Lager av värdepapper": { + "account_number": "1491" + }, + "Lager av fastigheter": { + "account_number": "1492" + }, + "Djur som klassificeras som omsättningstillgång": { + "account_number": "1493" + } + } + }, + "15 Kundfordringar": { + "account_type": "Receivable", + "is_group": 1, + "151 Kundfordringar": { + "is_group": 1, + "Kundfordringar": { + "account_number": "1510", + "account_type": "Receivable" + }, + "Kundfordringar ": { + "account_number": "1511", + "account_type": "Receivable" + }, + "Belånade kundfordringar (factoring)": { + "account_number": "1512", + "account_type": "Receivable" + }, + "Kundfordringar – delad faktura": { + "account_number": "1513", + "account_type": "Receivable" + }, + "Tvistiga kundfordringar": { + "account_number": "1516" + }, + "Ej reskontraförda kundfordringar": { + "account_number": "1518" + }, + "Nedskrivning av kundfordringar": { + "account_number": "1519", + "account_type": "Receivable" + } + }, + "152 Växelfordringar": { + "is_group": 1, + "Växelfordringar": { + "account_number": "1520" + }, + "Osäkra växelfordringar": { + "account_number": "1525" + }, + "Nedskrivning av växelfordringar": { + "account_number": "1529" + } + }, + "153 Kontraktsfordringar": { + "is_group": 1, + "Kontraktsfordringar": { + "account_number": "1530" + }, + "Kontraktsfordringar ": { + "account_number": "1531" + }, + "Belånade kontraktsfordringar": { + "account_number": "1532" + }, + "Tvistiga kontraktsfordringar": { + "account_number": "1536" + }, + "Nedskrivning av kontraktsfordringar": { + "account_number": "1539" + } + }, + "155 Konsignationsfordringar": { + "is_group": 1, + "Konsignationsfordringar": { + "account_number": "1550" + } + }, + "156 Kundfordringar hos koncernföretag": { + "is_group": 1, + "Kundfordringar hos koncernföretag": { + "account_number": "1560" + }, + "Kundfordringar hos moderföretag": { + "account_number": "1561" + }, + "Kundfordringar hos dotterföretag": { + "account_number": "1562" + }, + "Kundfordringar hos andra koncernföretag": { + "account_number": "1563" + }, + "Ej reskontraförda kundfordringar hos koncernföretag": { + "account_number": "1568" + }, + "Nedskrivning av kundfordringar hos koncernföretag": { + "account_number": "1569" + } + }, + "157 Kundfordringar hos intresseföretag, gemensamt styrda företag": { + "is_group": 1, + "Kundfordringar hos intresseföretag, gemensamt styrda företag": { + "account_number": "1570" + }, + "Kundfordringar hos intresseföretag": { + "account_number": "1571" + }, + "Kundfordringar hos gemensamt styrda företag": { + "account_number": "1572" + }, + "Kundfordringar hos övriga företag som det finns ett ägarintresse i": { + "account_number": "1573" + } + }, + "158 Fordringar för kontokort och kuponger": { + "is_group": 1, + "Fordringar för kontokort och kuponger": { + "account_number": "1580" + } + } + }, + "16 Övriga kortfristiga fordringar": { + "is_group": 1, + "161 Kortfristiga fordringar hos anställda": { + "is_group": 1, + "Kortfristiga fordringar hos anställda": { + "account_number": "1610" + }, + "Reseförskott": { + "account_number": "1611" + }, + "Kassaförskott": { + "account_number": "1612" + }, + "Övriga förskott": { + "account_number": "1613" + }, + "Tillfälliga lån till anställda": { + "account_number": "1614" + }, + "Övriga fordringar hos anställda": { + "account_number": "1619" + } + }, + "162 Upparbetad men ej fakturerad intäkt": { + "is_group": 1, + "Upparbetad men ej fakturerad intäkt": { + "account_number": "1620" + } + }, + "163 Avräkning för skatter och avgifter (skattekonto)": { + "is_group": 1, + "Avräkning för skatter och avgifter (skattekonto)": { + "account_number": "1630", + "account_type": "Tax" + } + }, + "164 Skattefordringar": { + "is_group": 1, + "Skattefordringar": { + "account_number": "1640" + } + }, + "165 Momsfordran": { + "is_group": 1, + "Momsfordran": { + "account_number": "1650" + } + }, + "166 Kortfristiga fordringar hos koncernföretag": { + "is_group": 1, + "Kortfristiga fordringar hos koncernföretag": { + "account_number": "1660" + }, + "Kortfristiga fordringar hos moderföretag": { + "account_number": "1661" + }, + "Kortfristiga fordringar hos dotterföretag": { + "account_number": "1662" + }, + "Kortfristiga fordringar hos andra koncernföretag": { + "account_number": "1663" + } + }, + "167 Kortfristiga fordringar hos intresseföretag, gemensamt styrda företag": { + "is_group": 1, + "Kortfristiga fordringar hos intresseföretag, gemensamt styrda företag": { + "account_number": "1670" + }, + "Kortfristiga fordringar hos intresseföretag": { + "account_number": "1671" + }, + "Kortfristiga fordringar hos gemensamt styrda företag": { + "account_number": "1672" + }, + "Kortfristiga fordringar hos övriga företag som det finns ett ögarintresse i": { + "account_number": "1673" + } + }, + "168 Andra kortfristiga fordringar": { + "is_group": 1, + "Andra kortfristiga fordringar": { + "account_number": "1680" + }, + "Utlägg för kunder": { + "account_number": "1681" + }, + "Kortfristiga lånefordringar": { + "account_number": "1682" + }, + "Derivat": { + "account_number": "1683" + }, + "Kortfristiga fordringar hos leverantörer": { + "account_number": "1684" + }, + "Kortfristiga fordringar hos delägare eller närstående": { + "account_number": "1685" + }, + "Kortfristig del av långfristiga fordringar": { + "account_number": "1687" + }, + "Fordran arbetsmarknadsförsäkringar": { + "account_number": "1688" + }, + "Övriga kortfristiga fordringar": { + "account_number": "1689" + } + }, + "169 Fordringar för tecknat men ej inbetalt aktiekapital": { + "is_group": 1, + "Fordringar för tecknat men ej inbetalt aktiekapital": { + "account_number": "1690" + } + } + }, + "17 Förutbetalda kostnader och upplupna intäkter": { + "is_group": 1, + "171 Förutbetalda hyreskostnader": { + "is_group": 1, + "Förutbetalda hyreskostnader": { + "account_number": "1710" + } + }, + "172 Förutbetalda leasingavgifter": { + "is_group": 1, + "Förutbetalda leasingavgifter": { + "account_number": "1720" + } + }, + "173 Förutbetalda försäkringspremier": { + "is_group": 1, + "Förutbetalda försäkringspremier": { + "account_number": "1730" + } + }, + "174 Förutbetalda räntekostnader": { + "is_group": 1, + "Förutbetalda räntekostnader": { + "account_number": "1740" + } + }, + "175 Upplupna hyresintäkter": { + "is_group": 1, + "Upplupna hyresintäkter": { + "account_number": "1750" + } + }, + "176 Upplupna ränteintäkter": { + "is_group": 1, + "Upplupna ränteintäkter": { + "account_number": "1760" + } + }, + "177 Tillgångar av kostnadsnatur": { + "is_group": 1, + "Tillgångar av kostnadsnatur": { + "account_number": "1770" + } + }, + "178 Upplupna avtalsintäkter": { + "is_group": 1, + "Upplupna avtalsintäkter": { + "account_number": "1780" + } + }, + "179 Övriga förutbetalda kostnader och upplupna intäkter": { + "is_group": 1, + "Övriga förutbetalda kostnader och upplupna intäkter": { + "account_number": "1790" + } + } + }, + "18 Kortfristiga placeringar": { + "is_group": 1, + "181 Andelar i börsnoterade företag": { + "is_group": 1, + "Andelar i börsnoterade företag": { + "account_number": "1810" + } + }, + "182 Obligationer": { + "is_group": 1, + "Obligationer": { + "account_number": "1820" + } + }, + "183 Konvertibla skuldebrev": { + "is_group": 1, + "Konvertibla skuldebrev": { + "account_number": "1830" + } + }, + "186 Andelar i koncernföretag, kortfristigt": { + "is_group": 1, + "Andelar i koncernföretag, kortfristigt": { + "account_number": "1860" + } + }, + "188 Andra kortfristiga placeringar": { + "is_group": 1, + "Andra kortfristiga placeringar": { + "account_number": "1880" + }, + "Derivat": { + "account_number": "1886" + }, + "Andelar i övriga företag": { + "account_number": "1889" + } + }, + "189 Nedskrivning av kortfristiga placeringar": { + "is_group": 1, + "Nedskrivning av kortfristiga placeringar": { + "account_number": "1890" + } + } + }, + "19 Kassa och bank": { + "account_type": "Cash", + "is_group": 1, + "191 Kassa": { + "is_group": 1, + "Kassa": { + "account_number": "1910", + "account_type": "Cash" + }, + "Huvudkassa": { + "account_number": "1911" + }, + "Kassa 2": { + "account_number": "1912" + }, + "Kassa 3": { + "account_number": "1913" + } + }, + "192 PlusGiro": { + "is_group": 1, + "PlusGiro": { + "account_number": "1920" + } + }, + "193 Företagskonto/checkkonto/affärskonto": { + "is_group": 1, + "Företagskonto/checkkonto/affärskonto": { + "account_number": "1930", + "account_type": "Bank" + } + }, + "194 Övriga bankkonton": { + "is_group": 1, + "Övriga bankkonton": { + "account_number": "1940" + } + }, + "195 Bankcertifikat": { + "is_group": 1, + "Bankcertifikat": { + "account_number": "1950" + } + }, + "196 Koncernkonto moderföretag": { + "is_group": 1, + "Koncernkonto moderföretag": { + "account_number": "1960" + } + }, + "197 Särskilda bankkonton": { + "is_group": 1, + "Särskilda bankkonton": { + "account_number": "1970" + }, + "Upphovsmannakonto": { + "account_number": "1972" + }, + "Skogskonto": { + "account_number": "1973" + }, + "Spärrade bankmedel": { + "account_number": "1974" + }, + "Övriga särskilda bankkonton": { + "account_number": "1979" + } + }, + "198 Valutakonton": { + "is_group": 1, + "Valutakonton": { + "account_number": "1980" + } + }, + "199 Redovisningsmedel": { + "is_group": 1, + "Redovisningsmedel": { + "account_number": "1990" + } + } + } + }, + "2 Eget Kapital och Skulder": { + "root_type": "Liability", + "is_group": 1, + "20 Eget Kapital": { + "account_type": "Equity", + "is_group": 1, + "201 Eget kapital, delägare 1": { + "is_group": 1, + "Eget kapital": { + "account_number": "2010", + "account_type": "Equity" + }, + "Egna varuuttag": { + "account_number": "2011", + "account_type": "Equity" + }, + "Övriga egna uttag": { + "account_number": "2013", + "account_type": "Equity" + }, + "Årets kapitaltillskott": { + "account_number": "2017", + "account_type": "Equity" + }, + "Övriga egna insättningar": { + "account_number": "2018", + "account_type": "Equity" + }, + "Årets resultat": { + "account_number": "2019", + "account_type": "Equity" + } + }, + "202 Eget kapital, delägare 2": { + "is_group": 1, + "Eget kapital": { + "account_number": "2020", + "account_type": "Equity" + }, + "Egna varuuttag": { + "account_number": "2021", + "account_type": "Equity" + }, + "Övriga egna uttag": { + "account_number": "2023", + "account_type": "Equity" + }, + "Årets kapitaltillskott": { + "account_number": "2027", + "account_type": "Equity" + }, + "Övriga egna insättningar": { + "account_number": "2028", + "account_type": "Equity" + }, + "Årets resultat": { + "account_number": "2029", + "account_type": "Equity" + } + }, + "203 Eget kapital, delägare 3": { + "is_group": 1, + "Eget kapital": { + "account_number": "2030", + "account_type": "Equity" + }, + "Egna varuuttag": { + "account_number": "2031", + "account_type": "Equity" + }, + "Övriga egna uttag": { + "account_number": "2033", + "account_type": "Equity" + }, + "Årets kapitaltillskott": { + "account_number": "2037", + "account_type": "Equity" + }, + "Övriga egna insättningar": { + "account_number": "2038", + "account_type": "Equity" + }, + "Årets resultat": { + "account_number": "2039", + "account_type": "Equity" + } + }, + "204 Eget kapital, delägare 4": { + "is_group": 1, + "Eget kapital": { + "account_number": "2040", + "account_type": "Equity" + }, + "Egna varuuttag": { + "account_number": "2041", + "account_type": "Equity" + }, + "Övriga egna uttag": { + "account_number": "2043", + "account_type": "Equity" + }, + "Årets kapitaltillskott": { + "account_number": "2047", + "account_type": "Equity" + }, + "Övriga egna insättningar": { + "account_number": "2048", + "account_type": "Equity" + }, + "Årets resultat": { + "account_number": "2049", + "account_type": "Equity" + } + }, + "205 Avsättning till expansionsfond": { + "is_group": 1, + "Avsättning till expansionsfond": { + "account_number": "2050" + } + }, + "206 Eget kapital i ideella föreningar, stiftelser och registrerade trossamfund": { + "is_group": 1, + "Eget kapital i ideella föreningar, stiftelser och registrerade trossamfund": { + "account_number": "2060", + "account_type": "Equity" + }, + "Eget kapital/stiftelsekapital/grundkapital": { + "account_number": "2061" + }, + "Förändring i fond för verkligt värde": { + "account_number": "2065" + }, + "Värdesäkringsfond": { + "account_number": "2066" + }, + "Balanserad vinst eller förlust/balanserat kapital": { + "account_number": "2067" + }, + "Vinst eller förlust från föregående år": { + "account_number": "2068" + }, + "Årets resultat": { + "account_number": "2069" + } + }, + "207 Ändamålsbestämda medel": { + "is_group": 1, + "Ändamålsbestämda medel": { + "account_number": "2070", + "account_type": "Equity" + }, + "Ändamål 1": { + "account_number": "2071" + }, + "Ändamål 2": { + "account_number": "2072" + } + }, + "208 Bundet eget kapital": { + "is_group": 1, + "Bundet eget kapital": { + "account_number": "2080" + }, + "Aktiekapital": { + "account_number": "2081", + "account_type": "Equity" + }, + "Ej registrerat aktiekapital": { + "account_number": "2082" + }, + "Medlemsinsatser": { + "account_number": "2083", + "account_type": "Equity" + }, + "Förlagsinsatser": { + "account_number": "2084" + }, + "Uppskrivningsfond": { + "account_number": "2085" + }, + "Reservfond": { + "account_number": "2086", + "account_type": "Equity" + }, + "Bunden överkursfond": { + "account_number": "2087" + }, + "Fond för yttre underhåll": { + "account_number": "2088" + }, + "Fond för utvecklingsutgifter": { + "account_number": "2089" + } + }, + "209 Fritt eget kapital": { + "is_group": 1, + "Fritt eget kapital": { + "account_number": "2090", + "account_type": "Equity" + }, + "Balanserad vinst eller förlust": { + "account_number": "2091", + "account_type": "Equity" + }, + "Mottagna/lämnade koncernbidrag": { + "account_number": "2092" + }, + "Erhållna aktieägartillskott": { + "account_number": "2093" + }, + "Egna aktier": { + "account_number": "2094" + }, + "Fusionsresultat": { + "account_number": "2095" + }, + "Fond för verkligt värde": { + "account_number": "2096" + }, + "Fri överkursfond": { + "account_number": "2097" + }, + "Vinst eller förlust från föregående år": { + "account_number": "2098", + "account_type": "Equity" + }, + "Årets resultat": { + "account_number": "2099", + "account_type": "Equity" + } + } + }, + "21 Obeskattade reserver": { + "root_type": "Equity", + "is_group": 1, + "211 Periodiseringsfonder": { + "account_type": "Equity", + "is_group": 1, + "Periodiseringsfonder": { + "account_number": "2110" + } + }, + "212 Periodiseringsfond 2020": { + "is_group": 1, + "Periodiseringsfond 2020": { + "account_number": "2120", + "account_type": "Equity" + }, + "Periodiseringsfond 2021": { + "account_number": "2121", + "account_type": "Equity" + }, + "Periodiseringsfond 2022": { + "account_number": "2122", + "account_type": "Equity" + }, + "Periodiseringsfond 2023": { + "account_number": "2123", + "account_type": "Equity" + }, + "Periodiseringsfond 2024": { + "account_number": "2124", + "account_type": "Equity" + }, + "Periodiseringsfond 2025": { + "account_number": "2125", + "account_type": "Equity" + }, + "Periodiseringsfond 2017": { + "account_number": "2127", + "account_type": "Equity" + }, + "Periodiseringsfond 2018": { + "account_number": "2128", + "account_type": "Equity" + }, + "Periodiseringsfond 2019": { + "account_number": "2129", + "account_type": "Equity" + } + }, + "213 Periodiseringsfond 2020": { + "is_group": 1, + "Periodiseringsfond 2020": { + "account_number": "2130", + "account_type": "Equity" + }, + "Periodiseringsfond 2021": { + "account_number": "2131", + "account_type": "Equity" + }, + "Periodiseringsfond 2022": { + "account_number": "2132", + "account_type": "Equity" + }, + "Periodiseringsfond 2023": { + "account_number": "2133", + "account_type": "Equity" + }, + "Periodiseringsfond 2024": { + "account_number": "2134", + "account_type": "Equity" + }, + "Periodiseringsfond 2025-2": { + "account_number": "2135", + "account_type": "Equity" + }, + "Periodiseringsfond 2017": { + "account_number": "2137", + "account_type": "Equity" + }, + "Periodiseringsfond 2018": { + "account_number": "2138", + "account_type": "Equity" + }, + "Periodiseringsfond 2019": { + "account_number": "2139", + "account_type": "Equity" + } + }, + "215 Ackumulerade överavskrivningar": { + "is_group": 1, + "Ackumulerade överavskrivningar": { + "account_number": "2150", + "account_type": "Equity" + }, + "Ackumulerade överavskrivningar på immateriella anläggningstillgångar": { + "account_number": "2151" + }, + "Ackumulerade överavskrivningar på byggnader och markanläggningar": { + "account_number": "2152" + }, + "Ackumulerade överavskrivningar på maskiner och inventarier": { + "account_number": "2153" + } + }, + "216 Ersättningsfond": { + "is_group": 1, + "Ersättningsfond": { + "account_number": "2160" + }, + "Ersättningsfond maskiner och inventarier": { + "account_number": "2161" + }, + "Ersättningsfond byggnader och markanläggningar": { + "account_number": "2162" + }, + "Ersättningsfond för djurlager i jordbruk och renskötsel": { + "account_number": "2164" + } + }, + "219 Övriga obeskattade reserver": { + "is_group": 1, + "Övriga obeskattade reserver": { + "account_number": "2190" + }, + "Lagerreserv": { + "account_number": "2196" + }, + "Övriga obeskattade reserver övriga": { + "account_number": "2199" + } + } + }, + "22 Avsättningar": { + "account_type": "Equity", + "is_group": 1, + "221 Avsättningar för pensioner enligt tryggandelagen": { + "account_type": "Equity", + "is_group": 1, + "Avsättningar för pensioner enligt tryggandelagen": { + "account_number": "2210", + "account_type": "Equity" + } + }, + "222 Avsättningar för garantier": { + "account_type": "Equity", + "is_group": 1, + "Avsättningar för garantier": { + "account_number": "2220", + "account_type": "Equity" + } + }, + "223 Övriga avsättningar för pensioner och liknande förpliktelser": { + "account_type": "Equity", + "is_group": 1, + "Övriga avsättningar för pensioner och liknande förpliktelser": { + "account_number": "2230" + } + }, + "224 Avsättningar för uppskjutna skatter": { + "is_group": 1, + "Avsättningar för uppskjutna skatter": { + "account_number": "2240" + } + }, + "225 Övriga avsättningar för skatter": { + "is_group": 1, + "Övriga avsättningar för skatter": { + "account_number": "2250" + }, + "Avsättningar för tvistiga skatter": { + "account_number": "2252" + }, + "Avsättningar särskild löneskatt, deklarationspost": { + "account_number": "2253" + } + }, + "229 Övriga avsättningar": { + "account_type": "Equity", + "is_group": 1, + "Övriga avsättningar": { + "account_number": "2290", + "account_type": "Equity" + } + } + }, + "23 Långfristiga skulder": { + "is_group": 1, + "231 Obligations- och förlagslån": { + "is_group": 1, + "Obligations- och förlagslån": { + "account_number": "2310" + } + }, + "232 Konvertibla lån och liknande": { + "is_group": 1, + "Konvertibla lån och liknande": { + "account_number": "2320" + }, + "Konvertibla lån": { + "account_number": "2321" + }, + "Lån förenade med optionsrätt": { + "account_number": "2322" + }, + "Vinstandelslån": { + "account_number": "2323" + }, + "Kapitalandelslån": { + "account_number": "2334" + } + }, + "233 Checkräkningskredit": { + "is_group": 1, + "Checkräkningskredit": { + "account_number": "2330" + }, + "Checkräkningskredit 1": { + "account_number": "2331" + }, + "Checkräkningskredit 2": { + "account_number": "2332" + } + }, + "234 Byggnadskreditiv": { + "is_group": 1, + "Byggnadskreditiv": { + "account_number": "2340" + } + }, + "235 Andra långfristiga skulder till kreditinstitut": { + "is_group": 1, + "Andra långfristiga skulder till kreditinstitut": { + "account_number": "2350" + }, + "Fastighetslån, långfristig del": { + "account_number": "2351" + }, + "Långfristiga lån i utländsk valuta från kreditinstitut": { + "account_number": "2355" + }, + "Övriga långfristiga lån från kreditinstitut": { + "account_number": "2359" + } + }, + "236 Långfristiga skulder till koncernfäretag": { + "is_group": 1, + "Långfristiga skulder till koncernfäretag": { + "account_number": "2360" + }, + "Långfristiga skulder till moderfäretag": { + "account_number": "2361" + }, + "Långfristiga skulder till dotterfäretag": { + "account_number": "2362" + }, + "Långfristiga skulder till andra koncernfäretag": { + "account_number": "2363" + } + }, + "237 Långfristiga skulder till intresseföretag, gemensamt styrda företag": { + "is_group": 1, + "Långfristiga skulder till intresseföretag, gemensamt styrda företag": { + "account_number": "2370" + }, + "Långfristiga skulder till intresseföretag": { + "account_number": "2371" + }, + "Långfristiga skulder till gemensamt styrda företag": { + "account_number": "2372" + }, + "Långfristiga skulder till övriga företag som det finns ett ägarintresse i": { + "account_number": "2373" + } + }, + "239 Övriga långfristiga skulder": { + "is_group": 1, + "Övriga långfristiga skulder": { + "account_number": "2390" + }, + "Avbetalningskontrakt, långfristig del": { + "account_number": "2391" + }, + "Villkorliga långfristiga skulder": { + "account_number": "2392" + }, + "Lån från närstående personer, långfristig del": { + "account_number": "2393" + }, + "Långfristiga leverantörskrediter": { + "account_number": "2394" + }, + "Andra långfristiga lån i utländsk valuta": { + "account_number": "2395" + }, + "Derivat": { + "account_number": "2396" + }, + "Mottagna depositioner, långfristiga": { + "account_number": "2397" + }, + "Övriga långfristiga skulder övriga": { + "account_number": "2399" + } + } + }, + "24 Kortfristiga skulder till kreditinstitut, kunder och leverantörer": { + "is_group": 1, + "241 Andra kortfristiga låneskulder till kreditinstitut": { + "is_group": 1, + "Andra kortfristiga låneskulder till kreditinstitut": { + "account_number": "2410", + "account_type": "Payable" + }, + "Kortfristiga lån från kreditinstitut": { + "account_number": "2411" + }, + "Byggnadskreditiv, kortfristig del": { + "account_number": "2412" + }, + "Kortfristig del av långfristiga skulder till kreditinstitut": { + "account_number": "2417" + }, + "Övriga kortfristiga skulder till kreditinstitut": { + "account_number": "2419" + } + }, + "242 Förskott från kunder": { + "is_group": 1, + "Förskott från kunder": { + "account_number": "2420", + "account_type": "Payable" + }, + "Ej inlösta presentkort": { + "account_number": "2421" + }, + "Övriga förskott från kunder": { + "account_number": "2429" + } + }, + "243 Pågående arbeten": { + "is_group": 1, + "Pågående arbeten": { + "account_number": "2430", + "account_type": "Payable" + }, + "Pågående arbeten, fakturering": { + "account_number": "2431" + }, + "Pågående arbeten, nedlagda kostnader": { + "account_number": "2438" + }, + "Beräknad fÖrändring av pågående arbeten": { + "account_number": "2439" + } + }, + "244 Leverantörsskulder": { + "is_group": 1, + "Leverantörsskulder": { + "account_number": "2440", + "account_type": "Payable" + }, + "Leverantörsskulder övriga": { + "account_number": "2441" + }, + "Konsignationsskulder": { + "account_number": "2443" + }, + "Tvistiga leverantörsskulder": { + "account_number": "2445" + }, + "Ej reskontraförda leverantörsskulder": { + "account_number": "2448", + "account_type": "Stock Received But Not Billed" + } + }, + "245 Fakturerad men ej upparbetad intäkt": { + "is_group": 1, + "Fakturerad men ej upparbetad intäkt": { + "account_number": "2450" + } + }, + "246 Leverantörsskulder till koncernföretag": { + "is_group": 1, + "Leverantörsskulder till koncernföretag": { + "account_number": "2460" + }, + "Leverantörsskulder till moderföretag": { + "account_number": "2461" + }, + "Leverantörsskulder till dotterföretag": { + "account_number": "2462" + }, + "Leverantörsskulder till andra koncernföretag": { + "account_number": "2463" + } + }, + "247 Leverantörsskulder till intresseföretag, gemensamt styrda företag och övriga företag som det finns ett ägarintresse i": { + "is_group": 1, + "Leverantörsskulder till intresseföretag, gemensamt styrda företag och övriga företag som det finns ett ägarintresse i": { + "account_number": "2470" + }, + "Leverantörsskulder till intresseföretag": { + "account_number": "2471" + }, + "Leverantörsskulder till gemensamt styrda företag": { + "account_number": "2472" + }, + "Leverantörsskulder till övriga företag som det finns ett ägarintresse i": { + "account_number": "2473" + } + }, + "248 Checkräkningskredit, kortfristig": { + "is_group": 1, + "Checkräkningskredit, kortfristig": { + "account_number": "2480" + } + }, + "249 Övriga kortfristiga skulder till kreditinstitut, kunder och leverantörer": { + "is_group": 1, + "Övriga kortfristiga skulder till kreditinstitut, kunder och leverantörer": { + "account_number": "2490" + }, + "Avräkning spelarrangörer": { + "account_number": "2491" + }, + "Växelskulder": { + "account_number": "2492" + }, + "Andra övriga kortfristiga skulder": { + "account_number": "2499" + } + } + }, + "25 Skatteskulder": { + "is_group": 1, + "251 Skatteskulder": { + "is_group": 1, + "Skatteskulder": { + "account_number": "2510" + }, + "Beräknad inkomstskatt": { + "account_number": "2512" + }, + "Beräknad fastighetsskatt/fastighetsavgift": { + "account_number": "2513" + }, + "Beräknad särskild löneskatt på pensionskostnader": { + "account_number": "2514" + }, + "Beräknad avkastningsskatt": { + "account_number": "2515" + }, + "Beräknad utländsk skatt": { + "account_number": "2517" + }, + "Betald F-skatt": { + "account_number": "2518" + } + } + }, + "26 Moms och punktskatter": { + "is_group": 1, + "261 Utgående moms, 25 %": { + "is_group": 1, + "Utgående moms, 25 %": { + "account_number": "2610", + "account_type": "Tax", + "tax_rate": 25.0 + }, + "Utgående moms på försäljning inom Sverige, 25 %": { + "account_number": "2611", + "account_type": "Tax", + "tax_rate": 25.0 + }, + "Utgående moms på egna uttag, 25 %": { + "account_number": "2612", + "account_type": "Tax", + "tax_rate": 25.0 + }, + "Utgående moms för uthyrning, 25 %": { + "account_number": "2613", + "account_type": "Tax", + "tax_rate": 25.0 + }, + "Utgående moms omvänd skattskyldighet, 25 %": { + "account_number": "2614", + "account_type": "Tax", + "tax_rate": 25.0 + }, + "Utgående moms import av varor, 25 %": { + "account_number": "2615", + "account_type": "Tax", + "tax_rate": 25.0 + }, + "Utgående moms VMB 25 %": { + "account_number": "2616", + "account_type": "Tax", + "tax_rate": 25.0 + }, + "Vilande utgående moms, 25 %": { + "account_number": "2618", + "account_type": "Tax", + "tax_rate": 25.0 + } + }, + "262 Utgående moms, 12 %": { + "is_group": 1, + "Utgående moms, 12 %": { + "account_number": "2620", + "account_type": "Tax", + "tax_rate": 12.0 + }, + "Utgående moms på försäljning inom Sverige, 12 %": { + "account_number": "2621", + "account_type": "Tax", + "tax_rate": 12.0 + }, + "Utgående moms på egna uttag, 12 %": { + "account_number": "2622", + "account_type": "Tax", + "tax_rate": 12.0 + }, + "Utgående moms för uthyrning, 12 %": { + "account_number": "2623", + "account_type": "Tax", + "tax_rate": 12.0 + }, + "Utgående moms omvänd skattskyldighet, 12 %": { + "account_number": "2624", + "account_type": "Tax", + "tax_rate": 12.0 + }, + "Utgående moms import av varor, 12 %": { + "account_number": "2625", + "account_type": "Tax", + "tax_rate": 12.0 + }, + "Utgående moms VMB 12 %": { + "account_number": "2626", + "account_type": "Tax", + "tax_rate": 12.0 + }, + "Vilande utgående moms, 12 %": { + "account_number": "2628", + "account_type": "Tax", + "tax_rate": 12.0 + } + }, + "263 Utgående moms, 6 %": { + "is_group": 1, + "Utgående moms, 6 %": { + "account_number": "2630", + "account_type": "Tax", + "tax_rate": 6.0 + }, + "Utgående moms på försäljning inom Sverige, 6 %": { + "account_number": "2631", + "account_type": "Tax", + "tax_rate": 6.0 + }, + "Utgående moms på egna uttag, 6 %": { + "account_number": "2632", + "account_type": "Tax", + "tax_rate": 6.0 + }, + "Utgående moms för uthyrning, 6 %": { + "account_number": "2633", + "account_type": "Tax", + "tax_rate": 6.0 + }, + "Utgående moms omvänd skattskyldighet, 6 %": { + "account_number": "2634", + "account_type": "Tax", + "tax_rate": 6.0 + }, + "Utgående moms import av varor, 6 %": { + "account_number": "2635", + "account_type": "Tax", + "tax_rate": 6.0 + }, + "Utgående moms VMB 6 %": { + "account_number": "2636", + "account_type": "Tax", + "tax_rate": 6.0 + }, + "Vilande utgående moms, 6 %": { + "account_number": "2638", + "account_type": "Tax", + "tax_rate": 6.0 + } + }, + "264 Ingående moms": { + "is_group": 1, + "Ingående moms": { + "account_number": "2640", + "account_type": "Tax" + }, + "Debiterad ingående moms": { + "account_number": "2641", + "account_type": "Tax" + }, + "Debiterad ingående moms i anslutning till frivillig skattskyldighet": { + "account_number": "2642", + "account_type": "Tax" + }, + "Beräknad ingående moms på förvärv från utlandet": { + "account_number": "2645", + "account_type": "Tax" + }, + "Ingående moms på uthyrning": { + "account_number": "2646", + "account_type": "Tax" + }, + "Ingående moms omvänd skattskyldighet varor och tjänster i Sverige": { + "account_number": "2647", + "account_type": "Tax" + }, + "Vilande ingående moms": { + "account_number": "2648", + "account_type": "Tax" + }, + "Ingående moms, blandad verksamhet": { + "account_number": "2649", + "account_type": "Tax" + } + }, + "265 Redovisningskonto för moms": { + "is_group": 1, + "Redovisningskonto för moms": { + "account_number": "2650", + "account_type": "Tax" + } + }, + "266 Punktskatter": { + "is_group": 1, + "Punktskatter": { + "account_number": "2660", + "account_type": "Tax" + } + }, + "267 Utgående moms, OSS": { + "is_group": 1, + "Utgående moms på försäljning inom EU, OSS": { + "account_number": "2670", + "account_type": "Tax" + } + } + }, + "27 Personalens skatter, avgifter och löneavdrag": { + "is_group": 1, + "271 Personalskatt": { + "is_group": 1, + "Personalskatt": { + "account_number": "2710" + } + }, + "273 Lagstadgade sociala avgifter och särskild löneskatt": { + "is_group": 1, + "Lagstadgade sociala avgifter och särskild löneskatt": { + "account_number": "2730" + }, + "Avräkning lagstadgade sociala avgifter": { + "account_number": "2731" + }, + "Avräkning särskild löneskatt": { + "account_number": "2732" + } + }, + "274 Avtalade sociala avgifter": { + "is_group": 1, + "Avtalade sociala avgifter": { + "account_number": "2740" + } + }, + "275 Utmätning i lön m.m.": { + "is_group": 1, + "Utmätning i lön m.m.": { + "account_number": "2750" + } + }, + "276 Semestermedel": { + "is_group": 1, + "Semestermedel": { + "account_number": "2760" + }, + "Avräkning semesterlöner": { + "account_number": "2761" + }, + "Semesterlönekassa": { + "account_number": "2762" + } + }, + "279 Övriga löneavdrag": { + "is_group": 1, + "Övriga löneavdrag": { + "account_number": "2790" + }, + "Personalens intressekonto": { + "account_number": "2791" + }, + "Lönsparande": { + "account_number": "2792" + }, + "Gruppförsäkringspremier": { + "account_number": "2793" + }, + "Fackföreningsavgifter": { + "account_number": "2794" + }, + "Mätnings- och granskningsarvoden": { + "account_number": "2795" + }, + "Övriga löneavdrag övriga": { + "account_number": "2799" + } + } + }, + "28 Övriga kortfristiga skulder": { + "is_group": 1, + "281 Avräkning för factoring och belånade kontraktsfordringar": { + "is_group": 1, + "Avräkning för factoring och belånade kontraktsfordringar": { + "account_number": "2810" + }, + "Avräkning för factoring": { + "account_number": "2811" + }, + "Avräkning för belånade kontraktsfordringar": { + "account_number": "2812" + } + }, + "282 Kortfristiga skulder till anställda": { + "is_group": 1, + "Kortfristiga skulder till anställda": { + "account_number": "2820" + }, + "Löneskulder": { + "account_number": "2821" + }, + "Reseräkningar": { + "account_number": "2822" + }, + "Tantiem, gratifikationer": { + "account_number": "2823" + }, + "Övriga kortfristiga skulder till anställda": { + "account_number": "2829" + } + }, + "283 Avräkning för annans räkning": { + "is_group": 1, + "Avräkning för annans räkning": { + "account_number": "2830" + } + }, + "284 Kortfristiga låneskulder": { + "is_group": 1, + "Kortfristiga låneskulder": { + "account_number": "2840" + }, + "Kortfristig del av långfristiga skulder": { + "account_number": "2841" + }, + "Övriga kortfristiga låneskulder": { + "account_number": "2849" + } + }, + "285 Avräkning för skatter och avgifter (skattekonto)": { + "is_group": 1, + "Avräkning för skatter och avgifter (skattekonto)": { + "account_number": "2850" + }, + "Anståndsbelopp för moms, arbetsgivaravgifter och personalskatt": { + "account_number": "2852" + } + }, + "286 Kortfristiga skulder till koncernföretag": { + "is_group": 1, + "Kortfristiga skulder till koncernföretag": { + "account_number": "2860" + }, + "Kortfristiga skulder till moderföretag": { + "account_number": "2861" + }, + "Kortfristiga skulder till dotterföretag": { + "account_number": "2862" + }, + "Kortfristiga skulder till andra koncernföretag": { + "account_number": "2863" + } + }, + "287 Kortfristiga skulder till intresseföretag, gemensamt styrda företag": { + "is_group": 1, + "Kortfristiga skulder till intresseföretag, gemensamt styrda företag": { + "account_number": "2870" + }, + "Kortfristiga skulder till intresseföretag": { + "account_number": "2871" + }, + "Kortfristiga skulder till gemensamt styrda företag": { + "account_number": "2872" + }, + "Kortfristiga skulder till övriga företag": { + "account_number": "2873" + } + }, + "288 Skuld erhållna bidrag": { + "is_group": 1, + "Skuld erhållna bidrag": { + "account_number": "2880" + } + }, + "289 Övriga kortfristiga skulder": { + "is_group": 1, + "Övriga kortfristiga skulder": { + "account_number": "2890" + }, + "Skulder under indrivning": { + "account_number": "2891" + }, + "Inre reparationsfond/underhållsfond": { + "account_number": "2892" + }, + "Skulder till närstående personer, kortfristig del": { + "account_number": "2893" + }, + "Derivat (kortfristiga skulder)": { + "account_number": "2895" + }, + "Mottagna depositioner, kortfristiga": { + "account_number": "2897" + }, + "Outtagen vinstutdelning": { + "account_number": "2898" + }, + "Övriga kortfristiga skulder övriga": { + "account_number": "2899" + } + } + }, + "29 Upplupna kostnader och förutbetalda intäkter": { + "is_group": 1, + "291 Upplupna löner": { + "is_group": 1, + "Upplupna löner": { + "account_number": "2910" + }, + "Löneskulder": { + "account_number": "2911" + }, + "Ackordsöverskott": { + "account_number": "2912" + }, + "Övriga upplupna löner": { + "account_number": "2919" + } + }, + "292 Upplupna semesterlöner": { + "is_group": 1, + "Upplupna semesterlöner": { + "account_number": "2920" + } + }, + "293 Upplupna pensionskostnader": { + "is_group": 1, + "Upplupna pensionskostnader": { + "account_number": "2930" + }, + "Upplupna pensionsutbetalningar": { + "account_number": "2931" + } + }, + "294 Upplupna lagstadgade sociala och andra avgifter": { + "is_group": 1, + "Upplupna lagstadgade sociala och andra avgifter": { + "account_number": "2940" + }, + "Beräknade upplupna lagstadgade sociala avgifter": { + "account_number": "2941" + }, + "Beräknad upplupen särskild löneskatt": { + "account_number": "2942" + }, + "Beräknad upplupen särskild löneskatt på pensionskostnader, deklarationspost": { + "account_number": "2943" + }, + "Beräknad upplupen avkastningsskatt på pensionskostnader": { + "account_number": "2944" + } + }, + "295 Upplupna avtalade sociala avgifter": { + "is_group": 1, + "Upplupna avtalade sociala avgifter": { + "account_number": "2950" + }, + "Upplupna avtalade arbetsmarknadsförsäkringar": { + "account_number": "2951" + }, + "Upplupna avtalade pensionsförsäkringsavgifter, deklarationspost": { + "account_number": "2959" + } + }, + "296 Upplupna räntekostnader": { + "is_group": 1, + "Upplupna räntekostnader": { + "account_number": "2960" + } + }, + "297 Förutbetalda intäkter": { + "is_group": 1, + "Förutbetalda intäkter": { + "account_number": "2970" + }, + "Förutbetalda hyresintäkter": { + "account_number": "2971" + }, + "Förutbetalda medlemsavgifter": { + "account_number": "2972" + }, + "Övriga förutbetalda intäkter": { + "account_number": "2979" + } + }, + "298 Upplupna avtalskostnader": { + "is_group": 1, + "Upplupna avtalskostnader": { + "account_number": "2980" + } + }, + "299 Övriga upplupna kostnader och förutbetalda intäkter": { + "is_group": 1, + "Övriga upplupna kostnader och förutbetalda intäkter": { + "account_number": "2990" + }, + "Beräknat arvode för bokslut": { + "account_number": "2991" + }, + "Beräknat arvode för revision": { + "account_number": "2992" + }, + "Ospecificerad skuld till leverantörer": { + "account_number": "2993" + }, + "Ej ankomna leverantörsfakturor": { + "account_number": "2995" + }, + "Övriga upplupna kostnader och förutbetalda intäkter övriga": { + "account_number": "2998" + }, + "OBS-konto": { + "account_number": "2999" + } + } + } + }, + "3 Rörelsens inkomster/intäkter": { + "root_type": "Income", + "is_group": 1, + "30 Huvudintäkter": { + "account_type": "Income Account", + "is_group": 1, + "300 Försäljning inom Sverige": { + "is_group": 1, + "Försäljning inom Sverige": { + "account_number": "3000", + "account_type": "Income Account" + }, + "Försäljning inom Sverige, 25 % moms": { + "account_number": "3001" + }, + "Försäljning inom Sverige, 12 % moms": { + "account_number": "3002" + }, + "Försäljning inom Sverige, 6 % moms": { + "account_number": "3003" + }, + "Försäljning inom Sverige, momsfri": { + "account_number": "3004" + } + } + }, + "31 Huvudintäkter": { + "account_type": "Income Account", + "is_group": 1, + "310 Försäljning av varor utanför Sverige": { + "is_group": 1, + "Försäljning av varor utanför Sverige": { + "account_number": "3100" + }, + "Försäljning varor till land utanför EU": { + "account_number": "3105" + }, + "Försäljning varor till annat EU-land, momspliktig": { + "account_number": "3106" + }, + "Försäljning varor till annat EU-land, momsfri": { + "account_number": "3108" + } + } + }, + "32 Huvudintäkter": { + "account_type": "Income Account", + "is_group": 1, + "320 Försäljning VMB och omvänd moms": { + "account_type": "Income Account", + "is_group": 1, + "Försäljning VMB och omvänd moms.": { + "account_number": "3200" + } + }, + "321 Försäljning positiv VMB 25 %": { + "is_group": 1, + "Försäljning positiv VMB 25 %": { + + "account_number": "3211" + }, + "Försäljning negativ VMB 25 %": { + + "account_number": "3212" + } + }, + "323 Försäljning inom byggsektorn, omvänd skattskyldighet moms": { + "account_type": "Income Account", + "is_group": 1, + "Försäljning inom byggsektorn, omvänd skattskyldighet moms": { + "account_number": "3231" + } + } + }, + "33 Huvudintäkter": { + "account_type": "Income Account", + "is_group": 1, + "330 Försäljning av tjänster utanför Sverige": { + "is_group": 1, + "Försäljning av tjänster utanför Sverige": { + "account_number": "3300" + }, + "Försäljning tjänster till land utanför EU": { + "account_number": "3305" + }, + "Försäljning tjänster till annat EU-land": { + "account_type": "Income Account" + } + } + }, + "34 Huvudintäkter": { + "account_type": "Income Account", + "is_group": 1, + "340 Försäljning, egna uttag": { + "is_group": 1, + "Försäljning, egna uttag": { + "account_number": "3400" + }, + "Egna uttag momspliktiga, 25 %": { + "account_number": "3401" + }, + "Egna uttag momspliktiga, 12 %": { + "account_number": "3402" + }, + "Egna uttag momspliktiga, 6 %": { + "account_number": "3403" + }, + "Egna uttag, momsfria": { + "account_number": "3404" + } + } + }, + "35 Fakturerade kostnader": { + "is_group": 1, + "350 Fakturerade kostnader (gruppkonto)": { + "account_type": "Income Account", + "is_group": 1, + "Fakturerade kostnader (gruppkonto)": { + "account_number": "3500" + } + }, + "351 Fakturerat emballage": { + "is_group": 1, + "Fakturerat emballage": { + "account_type": "Income Account", + "account_number": "3510" + }, + "Fakturerat emballage.": { + "account_number": "3511" + }, + "Returnerat emballage": { + "account_number": "3518" + } + }, + "352 Fakturerade frakter": { + "is_group": 1, + "Fakturerade frakter": { + "account_type": "Income Account", + "account_number": "3520" + }, + "Fakturerade frakter, EU-land": { + "account_type": "Income Account", + "account_number": "3521" + }, + "Fakturerade frakter, export": { + "account_type": "Income Account", + "account_number": "3522" + } + }, + "353 Fakturerade tull- och speditionskostnader m.m.": { + "account_type": "Income Account", + "is_group": 1, + "Fakturerade tull- och speditionskostnader m.m.": { + "account_number": "3530" + } + }, + "354 Faktureringsavgifter": { + "account_type": "Income Account", + "is_group": 1, + "Faktureringsavgifter": { + "account_type": "Income Account", + "account_number": "3540" + }, + "Faktureringsavgifter, EU-land": { + "account_type": "Income Account", + "account_number": "3541" + }, + "Faktureringsavgifter, export": { + "account_type": "Income Account", + "account_number": "3542" + } + }, + "355 Fakturerade resekostnader": { + "account_type": "Income Account", + "is_group": 1, + "Fakturerade resekostnader": { + "account_number": "3550" + } + }, + "356 Fakturerade kostnader till koncernföretag": { + "account_type": "Income Account", + "is_group": 1, + "Fakturerade kostnader till koncernföretag": { + "account_number": "3560" + }, + "Fakturerade kostnader till moderföretag": { + "account_number": "3561" + }, + "Fakturerade kostnader till dotterföretag": { + "account_number": "3562" + }, + "Fakturerade kostnader till andra koncernföretag": { + "account_number": "3563" + } + }, + "357 Fakturerade kostnader till intresseföretag, gemensamt styrda företag och övriga företag": { + "account_type": "Income Account", + "is_group": 1, + "Fakturerade kostnader till intresseföretag, gemensamt styrda företag": { + "account_number": "3570" + } + }, + "359 Övriga fakturerade kostnader": { + "account_type": "Income Account", + "is_group": 1, + "Övriga fakturerade kostnader": { + "account_number": "3590" + } + } + }, + "36 Rörelsens sidointäkter": { + "is_group": 1, + "360 Rörelsens sidointäkter (gruppkonto)": { + "account_type": "Income Account", + "is_group": 1, + "Rörelsens sidointäkter (gruppkonto)": { + "account_number": "3600" + } + }, + "361 Försäljning av material": { + "is_group": 1, + "Försäljning av material": { + "account_number": "3610" + }, + "Försäljning av råmaterial": { + "account_number": "3611" + }, + "Försäljning av skrot": { + "account_number": "3612" + }, + "Försäljning av förbrukningsmaterial": { + "account_number": "3613" + }, + "Försäljning av övrigt material": { + "account_number": "3619" + } + }, + "362 Tillfällig uthyrning av personal": { + "account_type": "Income Account", + "is_group": 1, + "Tillfällig uthyrning av personal": { + "account_number": "3620" + } + }, + "363 Tillfällig uthyrning av transportmedel": { + "account_type": "Income Account", + "is_group": 1, + "Tillfällig uthyrning av transportmedel": { + "account_number": "3630" + } + }, + "367 Intäkter från värdepapper": { + "is_group": 1, + "Intäkter från värdepapper": { + "account_number": "3670" + }, + "Försäljning av värdepapper": { + "account_number": "3671" + }, + "Utdelning från värdepapper": { + "account_number": "3672" + }, + "Övriga intäkter från värdepapper": { + "account_number": "3679" + } + }, + "368 Management fees": { + "account_type": "Income Account", + "is_group": 1, + "Management fees": { + "account_number": "3680" + } + }, + "369 Övriga sidointäkter": { + "account_type": "Income Account", + "is_group": 1, + "Övriga sidointäkter": { + "account_number": "3690" + } + } + }, + "37 Intäktskorrigeringar": { + "is_group": 1, + "370 Intäktskorrigeringar (gruppkonto)": { + "account_type": "Income Account", + "is_group": 1, + "Intäktskorrigeringar (gruppkonto)": { + "account_number": "3700" + } + }, + "371 Ofördelade intäktsreduktioner": { + "is_group": 1, + "Ofördelade intäktsreduktioner": { + "account_number": "3710" + } + }, + "373 Lämnade rabatter": { + "is_group": 1, + "Lämnade rabatter": { + "account_number": "3730" + }, + "Lämnade kassarabatter": { + "account_number": "3731" + }, + "Lämnade mängdrabatter": { + "account_number": "3732" + } + }, + "374 Öres- och kronutjämning": { + "is_group": 1, + "Öres- och kronutjämning": { + "account_number": "3740", + "account_type": "Round Off" + } + }, + "375 Punktskatter": { + "is_group": 1, + "Punktskatter": { + "account_number": "3750" + }, + "Intäktsförda punktskatter (kreditkonto)": { + "account_number": "3751" + }, + "Skuldförda punktskatter (debetkonto)": { + "account_number": "3752" + } + }, + "379 Övriga intäktskorrigeringar": { + + "is_group": 1, + "Övriga intäktskorrigeringar": { + "account_number": "3790" + } + } + }, + "38 Aktiverat arbete för egen räkning": { + "is_group": 1, + "380 Aktiverat arbete för egen räkning (gruppkonto)": { + "account_type": "Income Account", + "is_group": 1, + "Aktiverat arbete för egen räkning (gruppkonto)": { + "account_number": "3800" + } + }, + "384 Aktiverat arbete (material)": { + "account_type": "Income Account", + "is_group": 1, + "Aktiverat arbete (material)": { + "account_number": "3840" + } + }, + "385 Aktiverat arbete (omkostnader)": { + "account_type": "Income Account", + "is_group": 1, + "Aktiverat arbete (omkostnader)": { + "account_number": "3850" + } + }, + "387 Aktiverat arbete (personal)": { + "account_type": "Income Account", + "is_group": 1, + "Aktiverat arbete (personal)": { + "account_number": "3870" + } + } + }, + "39 Övriga rörelseintäkter": { + "account_type": "Income Account", + "is_group": 1, + "390 Övriga rörelseintäkter (gruppkonto)": { + "account_type": "Income Account", + "is_group": 1, + "Övriga rörelseintäkter (gruppkonto)": { + "account_number": "3900" + } + }, + "391 Hyres- och arrendeintäkter": { + "is_group": 1, + "Hyres- och arrendeintäkter": { + "account_number": "3910" + }, + "Hyresintäkter": { + "account_number": "3911" + }, + "Arrendeintäkter": { + "account_number": "3912" + }, + "Frivilligt momspliktiga hyresintäkter": { + + "account_number": "3913" + }, + "Övriga momspliktiga hyresintäkter": { + "account_number": "3914" + } + }, + "392 Provisionsintäkter, licensintäkter och royalties": { + "is_group": 1, + "Provisionsintäkter, licensintäkter och royalties": { + "account_number": "3920" + }, + "Provisionsintäkter": { + "account_number": "3921" + }, + "Licensintäkter och royalties": { + "account_number": "3922" + }, + "Franchiseintäkter": { + "account_number": "3925" + } + }, + "394 Orealiserade negativa/positiva värdeförändringar på säkringsinstrument": { + "account_type": "Income Account", + "is_group": 1, + "Orealiserade negativa/positiva värdeförändringar på säkringsinstrument": { + "account_number": "3940" + } + }, + "395 Återvunna, tidigare avskrivna kundfordringar": { + "account_type": "Income Account", + "is_group": 1, + "Återvunna, tidigare avskrivna kundfordringar": { + "account_number": "3950" + } + }, + "396 Valutakursvinster på fordringar och skulder av rörelsekaraktär": { + "account_type": "Income Account", + "is_group": 1, + "Valutakursvinster på fordringar och skulder av rörelsekaraktär": { + "account_number": "3960" + } + }, + "397 Vinst vid avyttring av immateriella och materiella anläggningstillgångar": { + "is_group": 1, + "Vinst vid avyttring av immateriella och materiella anläggningstillgångar": { + + "account_number": "3970" + }, + "Vinst vid avyttring av immateriella anläggningstillgångar": { + "account_number": "3971" + }, + "Vinst vid avyttring av byggnader och mark": { + "account_number": "3972" + }, + "Vinst vid avyttring av maskiner och inventarier": { + "account_number": "3973" + } + }, + "398 Erhållna offentliga bidrag": { + "is_group": 1, + "Erhållna offentliga bidrag": { + + "account_number": "3980" + }, + "Erhållna EU-bidrag": { + "account_number": "3981" + }, + "Erhållna statliga bidrag": { + "account_number": "3985" + }, + "Erhållna kommunala bidrag": { + "account_number": "3987" + }, + "Erhållna offentliga bidrag för personal": { + "account_number": "3988" + }, + "Övriga erhållna offentliga bidrag": { + "account_number": "3989" + } + }, + "399 Övriga ersättningar, bidrag och intäkter": { + "is_group": 1, + "Övriga ersättningar, bidrag och intäkter": { + "account_number": "3990" + }, + "Konfliktersättning": { + "account_number": "3991" + }, + "Erhållna skadestånd": { + "account_number": "3992" + }, + "Erhållna donationer och gåvor": { + "account_number": "3993" + }, + "Försäkringsersättningar": { + "account_number": "3994" + }, + "Erhållet ackord på skulder av rörelsekaraktär": { + "account_number": "3995" + }, + "Erhållna reklambidrag": { + "account_number": "3996" + }, + "Sjuklöneersättning": { + "account_number": "3997" + }, + "Återbäring av överskott från försäkringsföretag": { + "account_number": "3998" + }, + "Övriga rörelseintäkter": { + "account_number": "3999" + } + } + } + }, + "4 Utgifter/kostnader för varor, material och vissa köpta tjänster": { + "root_type": "Expense", + "is_group": 1, + "40 Inköp av varor och material": { + "account_type": "Expense Account", + "is_group": 1, + "400 Inköp av varor från Sverige": { + "is_group": 1, + "Inköp av varor från Sverige": { + "account_number": "4000", + "account_type": "Expense Account" + } + } + }, + "41 Inköp av varor och material": { + "account_type": "Expense Account", + "is_group": 1, + "410 Inköp av varor från Sverige": { + "is_group": 1, + "Inköp av varor från Sverige": { + "account_number": "4100", + "account_type": "Expense Account" + } + } + }, + "42 Inköp av varor och material": { + "is_group": 1, + "420 Sålda varor VMB": { + "is_group": 1, + "Sålda varor VMB": { + "account_number": "4200", + "account_type": "Expense Account" + } + }, + "421 Sålda varor positiv VMB 25 %": { + "is_group": 1, + "Sålda varor positiv VMB 25 %": { + "account_number": "4211", + "account_type": "Expense Account" + }, + "Sålda varor negativ VMB 25 %": { + "account_number": "4212", + "account_type": "Expense Account" + } + } + }, + "43 Inköp av varor och material": { + "account_type": "Expense Account", + "is_group": 1, + "430 Inköp av varor från Sverige": { + "is_group": 1, + "Inköp av varor från Sverige": { + "account_number": "4300", + "account_type": "Expense Account" + } + } + }, + "44 Inköp av varor och material": { + "is_group": 1, + "440 Momspliktiga inköp i Sverige": { + "is_group": 1, + "Momspliktiga inköp i Sverige": { + "account_number": "4400", + "account_type": "Expense Account" + } + }, + "441 Inköpta varor i Sverige, omvänd skattskyldighet": { + "is_group": 1, + "Inköpta varor i Sverige, omvänd skattskyldighet, 25 % moms": { + "account_number": "4415", + "account_type": "Expense Account" + }, + "Inköpta varor i Sverige, omvänd skattskyldighet, 12 % moms": { + "account_number": "4416", + "account_type": "Expense Account" + }, + "Inköpta varor i Sverige, omvänd skattskyldighet, 6 % moms": { + "account_number": "4417", + "account_type": "Expense Account" + } + }, + "442 Inköpta tjänster i Sverige, omvänd skattskyldighet": { + "is_group": 1, + "Inköpta tjänster i Sverige, omvänd skattskyldighet, 25 % moms": { + "account_number": "4425", + "account_type": "Expense Account" + }, + "Inköpta tjänster i Sverige, omvänd skattskyldighet, 12 %": { + "account_number": "4426", + "account_type": "Expense Account" + }, + "Inköpta tjänster i Sverige, omvänd skattskyldighet, 6 %": { + "account_number": "4427", + "account_type": "Expense Account" + } + } + }, + "45 Inköp av varor och material": { + "is_group": 1, + "450 Övriga momspliktiga inköp": { + "is_group": 1, + "Övriga momspliktiga inköp": { + "account_number": "4500", + "account_type": "Expense Account" + } + }, + "451 Inköp av varor från annat EU-land": { + "is_group": 1, + "Inköp av varor från annat EU-land, 25 %": { + "account_number": "4515", + "account_type": "Expense Account" + }, + "Inköp av varor från annat EU-land, 12 %": { + "account_number": "4516", + "account_type": "Expense Account" + }, + "Inköp av varor från annat EU-land, 6 %": { + "account_number": "4517", + "account_type": "Expense Account" + }, + "Inköp av varor från annat EU-land, momsfri": { + "account_number": "4518", + "account_type": "Expense Account" + } + }, + "453 Inköp av tjänster från ett land utanför EU": { + "is_group": 1, + "Inköp av tjänster från ett land utanför EU, 25 % moms": { + "account_number": "4531", + "account_type": "Expense Account" + }, + "Inköp av tjänster från ett land utanför EU, 12 % moms": { + "account_number": "4532", + "account_type": "Expense Account" + }, + "Inköp av tjänster från ett land utanför EU, 6 % moms": { + "account_number": "4533", + "account_type": "Expense Account" + }, + "Inköp av tjänster från annat EU-land, 25 %": { + "account_number": "4535", + "account_type": "Expense Account" + }, + "Inköp av tjänster från annat EU-land, 12 %": { + "account_number": "4536", + "account_type": "Expense Account" + }, + "Inköp av tjänster från annat EU-land, 6 %": { + "account_number": "4537", + "account_type": "Expense Account" + }, + "Inköp av tjänster från annat EU-land, momsfri": { + "account_number": "4538", + "account_type": "Expense Account" + } + }, + "454 Import av varor": { + "is_group": 1, + "Import av varor, 25 % moms": { + "account_number": "4545", + "account_type": "Expense Account" + }, + "Import av varor, 12 % moms": { + "account_number": "4546", + "account_type": "Expense Account" + }, + "Import av varor, 6 % moms": { + "account_number": "4547", + "account_type": "Expense Account" + } + } + }, + "46 Legoarbeten, underentreprenader": { + "is_group": 1, + "460 Legoarbeten och underentreprenader (gruppkonto)": { + "is_group": 1, + "Legoarbeten och underentreprenader (gruppkonto)": { + "account_number": "4600", + "account_type": "Expense Account" + } + } + }, + "47 Reduktion av inköpspriser": { + "is_group": 1, + "470 Reduktion av inköpspriser (gruppkonto)": { + "account_type": "Expense Account", + "is_group": 1, + "Reduktion av inköpspriser (gruppkonto)": { + "account_number": "4700", + "account_type": "Expense Account" + } + }, + "473 Erhållna rabatter": { + "is_group": 1, + "Erhållna rabatter": { + "account_number": "4730" + }, + "Erhållna kassarabatter": { + "account_number": "4731" + }, + "Erhållna mängdrabatter (inkl. bonus)": { + "account_number": "4732" + }, + "Erhållet aktivitetsstöd": { + "account_number": "4733" + } + }, + "479 Övriga reduktioner av inköpspriser": { + "is_group": 1, + "Övriga reduktioner av inköpspriser": { + "account_number": "4790" + } + } + }, + "49 Förändring av lager, produkter i arbete och pågående arbeten": { + "is_group": 1, + "490 Förändring av lager (gruppkonto)": { + "is_group": 1, + "Förändring av lager (gruppkonto)": { + "account_number": "4900", + "account_type": "Stock Adjustment" + } + }, + "491 Förändring av lager av råvaror": { + "is_group": 1, + "Förändring av lager av råvaror": { + "account_number": "4910", + "account_type": "Expense Account" + } + }, + "492 Förändring av lager av tillsatsmaterial och förnödenheter": { + "is_group": 1, + "Förändring av lager av tillsatsmaterial och förnödenheter": { + "account_number": "4920", + "account_type": "Expense Account" + } + }, + "494 Förändring av produkter i arbete": { + "is_group": 1, + "Förändring av produkter i arbete": { + "account_number": "4940", + "account_type": "Expense Account" + }, + "Förändring av produkter i arbete, material och utlägg": { + "account_number": "4944" + }, + "Förändring av produkter i arbete, omkostnader": { + "account_number": "4945" + }, + "Förändring av produkter i arbete, personalkostnader": { + "account_number": "4947" + } + }, + "495 Förändring av lager av färdiga varor": { + "is_group": 1, + "Förändring av lager av färdiga varor": { + "account_number": "4950", + "account_type": "Expense Account" + } + }, + "496 Förändring av lager av handelsvaror": { + "is_group": 1, + "Förändring av lager av handelsvaror": { + "account_number": "4960", + "account_type": "Stock Adjustment" + } + }, + "497 Förändring av pågående arbeten, nedlagda kostnader": { + "is_group": 1, + "Förändring av pågående arbeten, nedlagda kostnader": { + "account_number": "4970", + "account_type": "Expense Account" + }, + "Förändring av pågående arbeten, material och utlägg": { + "account_number": "4974" + }, + "Förändring av pågående arbeten, omkostnader": { + "account_number": "4975" + }, + "Förändring av pågående arbeten, personalkostnader": { + "account_number": "4977" + } + }, + "498 Förändring av lager av värdepapper": { + "is_group": 1, + "Förändring av lager av värdepapper": { + "account_number": "4980" + }, + "Sålda värdepappers anskaffningsvärde": { + "account_number": "4981" + }, + "Nedskrivning av värdepapper": { + "account_number": "4987" + }, + "Återföring av nedskrivning av värdepapper": { + "account_number": "4988" + } + } + } + }, + "5 Övriga externa rörelseutgifter/kostnader": { + "root_type": "Expense", + "is_group": 1, + "50 Lokalkostnader": { + "is_group": 1, + "500 Lokalkostnader (gruppkonto)": { + "account_type": "Expense Account", + "is_group": 1, + "Lokalkostnader (gruppkonto)": { + "account_number": "5000" + } + }, + "501 Lokalhyra": { + "is_group": 1, + "Lokalhyra": { + "account_number": "5010", + "account_type": "Expense Account" + }, + "Hyra för kontorslokaler": { + "account_number": "5011" + }, + "Hyra för garage": { + "account_number": "5012" + }, + "Hyra för lagerlokaler": { + "account_number": "5013" + } + }, + "502 El för belysning": { + "is_group": 1, + "El för belysning": { + "account_number": "5020", + "account_type": "Expense Account" + } + }, + "503 Värme": { + "is_group": 1, + "Värme": { + "account_number": "5030", + "account_type": "Expense Account" + } + }, + "504 Vatten och avlopp": { + "is_group": 1, + "Vatten och avlopp": { + "account_number": "5040", + "account_type": "Expense Account" + } + }, + "505 Lokaltillbehör": { + "is_group": 1, + "Lokaltillbehör": { + "account_number": "5050", + "account_type": "Expense Account" + } + }, + "506 Städning och renhållning": { + "is_group": 1, + "Städning och renhållning": { + "account_number": "5060", + "account_type": "Expense Account" + }, + "Städning": { + "account_number": "5061" + }, + "Sophämtning": { + "account_number": "5062" + }, + "Hyra för sopcontainer": { + "account_number": "5063" + }, + "Snöröjning": { + "account_number": "5064" + }, + "Trädgårdsskötsel": { + "account_number": "5065" + } + }, + "507 Reparation och underhåll av lokaler": { + "is_group": 1, + "Reparation och underhåll av lokaler": { + "account_number": "5070", + "account_type": "Expense Account" + } + }, + "509 Övriga lokalkostnader": { + "account_type": "Expense Account", + "is_group": 1, + "Övriga lokalkostnader": { + "account_number": "5090" + }, + "Övriga lokalkostnader, avdragsgilla": { + "account_number": "5098" + }, + "Övriga lokalkostnader, ej avdragsgilla": { + "account_number": "5099" + } + } + }, + "51 Fastighetskostnader": { + "is_group": 1, + "510 Fastighetskostnader (gruppkonto)": { + "account_type": "Expense Account", + "is_group": 1, + "Fastighetskostnader (gruppkonto)": { + "account_number": "5100" + } + }, + "511 Tomträttsavgäld/arrende": { + "account_type": "Expense Account", + "is_group": 1, + "Tomträttsavgäld/arrende": { + "account_number": "5110" + } + }, + "512 El för belysning": { + "is_group": 1, + "El för belysning": { + "account_number": "5120", + "account_type": "Expense Account" + } + }, + "513 Värme": { + "is_group": 1, + "Värme": { + "account_number": "5130", + "account_type": "Expense Account" + }, + "Uppvärmninig": { + "account_number": "5131", + "account_type": "Expense Account" + }, + "Sotning": { + "account_number": "5132", + "account_type": "Expense Account" + } + }, + "514 Vatten och avlopp": { + "is_group": 1, + "Vatten och avlopp": { + "account_number": "5140", + "account_type": "Expense Account" + } + }, + "516 Städning och renhållning": { + "is_group": 1, + "Städning och renhållning": { + "account_number": "5160", + "account_type": "Expense Account" + }, + "Städning": { + "account_number": "5161" + }, + "Sophämtning": { + "account_number": "5162" + }, + "Hyra för sopcontainer": { + "account_number": "5163" + }, + "Snöröjning": { + "account_number": "5164" + }, + "Trädgårdsskötsel": { + "account_number": "5165" + } + }, + "517 Reparation och underhåll av fastighet": { + "is_group": 1, + "Reparation och underhåll av fastighet": { + "account_number": "5170", + "account_type": "Expense Account" + } + }, + "519 Övriga fastighetskostnader": { + "is_group": 1, + "Övriga fastighetskostnader": { + "account_number": "5190" + }, + "Fastighetsskatt/fastighetsavgift": { + "account_number": "5191" + }, + "Fastighetsförsäkringspremier": { + "account_number": "5192" + }, + "Fastighetsskötsel och förvaltning": { + "account_number": "5193" + }, + "Övriga fastighetskostnader, avdragsgilla": { + "account_number": "5198" + }, + "Övriga fastighetskostnader, ej avdragsgilla": { + "account_number": "5199" + } + } + }, + "52 Hyra av anläggningstillgångar": { + "is_group": 1, + "520 Hyra av anläggningstillgångar (gruppkonto)": { + "is_group": 1, + "Hyra av anläggningstillgångar (gruppkonto)": { + "account_number": "5200", + "account_type": "Expense Account" + } + }, + "521 Hyra av maskiner och andra tekniska anläggningar": { + "is_group": 1, + "Hyra av maskiner och andra tekniska anläggningar": { + "account_number": "5210", + "account_type": "Expense Account" + }, + "Korttidshyra av maskiner och andra tekniska anläggningar": { + "account_number": "5211", + "account_type": "Expense Account" + }, + "Leasing av maskiner och andra tekniska anläggningar": { + "account_number": "5212", + "account_type": "Expense Account" + } + }, + "522 Hyra av inventarier och verktyg": { + "is_group": 1, + "Hyra av inventarier och verktyg": { + "account_number": "5220" + }, + "Korttidshyra av inventarier och verktyg": { + "account_number": "5221" + }, + "Leasing av inventarier och verktyg": { + "account_number": "5222" + } + }, + "525 Hyra av datorer": { + "is_group": 1, + "Hyra av datorer": { + "account_number": "5250" + }, + "Korttidshyra av datorer": { + "account_number": "5251" + }, + "Leasing av datorer": { + "account_number": "5252" + } + }, + "529 Övriga hyreskostnader för anläggningstillgångar": { + "account_type": "Expense Account", + "is_group": 1, + "Övriga hyreskostnader för anläggningstillgångar": { + "account_number": "5290" + } + } + }, + "53 Energikostnader": { + "is_group": 1, + "530 Energikostnader (gruppkonto)": { + "is_group": 1, + "Energikostnader (gruppkonto)": { + "account_number": "5300", + "account_type": "Expense Account" + } + }, + "531 El för drift": { + "account_type": "Expense Account", + "is_group": 1, + "El för drift": { + "account_number": "5310" + } + }, + "532 Gas": { + "account_type": "Expense Account", + "is_group": 1, + "Gas": { + "account_number": "5320" + } + }, + "533 Eldningsolja": { + "account_type": "Expense Account", + "is_group": 1, + "Eldningsolja": { + "account_number": "5330" + } + }, + "534 Stenkol och koks": { + "account_type": "Expense Account", + "is_group": 1, + "Stenkol och koks": { + "account_number": "5340" + } + }, + "535 Torv, träkol, ved och annat träbränsle": { + "account_type": "Expense Account", + "is_group": 1, + "Torv, träkol, ved och annat träbränsle": { + "account_number": "5350" + } + }, + "536 Bensin, fotogen och motorbrännolja": { + "account_type": "Expense Account", + "is_group": 1, + "Bensin, fotogen och motorbrännolja": { + "account_number": "5360" + } + }, + "537 Fjärrvärme, kyla och ånga": { + "account_type": "Expense Account", + "is_group": 1, + "Fjärrvärme, kyla och ånga": { + "account_number": "5370" + } + }, + "538 Vatten": { + "account_type": "Expense Account", + "is_group": 1, + "Vatten": { + "account_number": "5380" + } + }, + "539 Övriga energikostnader": { + "account_type": "Expense Account", + "is_group": 1, + "Övriga energikostnader": { + "account_number": "5390" + } + } + }, + "54 Förbrukningsinventarier och förbrukningsmaterial": { + "is_group": 1, + "540 Förbrukningsinventarier och förbrukningsmaterial": { + "is_group": 1, + "Förbrukningsinventarier och förbrukningsmaterial": { + "account_number": "5400" + } + }, + "541 Förbrukningsinventarier": { + "is_group": 1, + "Förbrukningsinventarier": { + "account_number": "5410", + "account_type": "Expense Account" + }, + "Förbrukningsinventarier med en livslängd på mer än ett år": { + "account_number": "5411", + "account_type": "Expense Account" + }, + "Förbrukningsinventarier med en livslängd på ett år eller mindre": { + "account_number": "5412", + "account_type": "Expense Account" + } + }, + "542 Programvaror": { + "is_group": 1, + "Programvaror": { + "account_number": "5420", + "account_type": "Expense Account" + } + }, + "543 Transportinventarier": { + "account_type": "Expense Account", + "is_group": 1, + "Transportinventarier": { + "account_number": "5430" + } + }, + "544 Förbrukningsemballage": { + "account_type": "Expense Account", + "is_group": 1, + "Förbrukningsemballage": { + "account_number": "5440" + } + }, + "546 Förbrukningsmaterial": { + "is_group": 1, + "BFörbrukningsmaterial": { + "account_number": "5460", + "account_type": "Expense Account" + } + }, + "548 Arbetskläder och skyddsmaterial": { + "account_type": "Expense Account", + "is_group": 1, + "Arbetskläder och skyddsmaterial": { + "account_number": "5480" + } + }, + "549 Övriga förbrukningsinventarier och förbrukningsmaterial": { + "account_type": "Expense Account", + "is_group": 1, + "Övriga förbrukningsinventarier och förbrukningsmaterial": { + "account_number": "5490" + }, + "Övriga förbrukningsinventarier med en livslängd på mer än ett år": { + "account_number": "5491" + }, + "Övriga förbrukningsinventarier med en livslängd på ett år eller mindre": { + "account_number": "5492" + }, + "Övrigt förbrukningsmaterial": { + "account_number": "5493" + } + } + }, + "55 Reparation och underhåll": { + "account_type": "Expense Account", + "is_group": 1, + "550 Reparation och underhåll (gruppkonto)": { + "is_group": 1, + "Reparation och underhåll (gruppkonto)": { + "account_number": "5500", + "account_type": "Expense Account" + } + }, + "551 Reparation och underhåll av maskiner och andra tekniska anläggningar": { + "account_type": "Expense Account", + "is_group": 1, + "Reparation och underhåll av maskiner och andra tekniska anläggningar": { + "account_number": "5510" + } + }, + "552 Reparation och underhåll av inventarier, verktyg och datorer m.m.": { + "account_type": "Expense Account", + "is_group": 1, + "Reparation och underhåll av inventarier, verktyg och datorer m.m.": { + "account_number": "5520" + } + }, + "553 Reparation och underhåll av installationer": { + "account_type": "Expense Account", + "is_group": 1, + "Reparation och underhåll av installationer": { + "account_number": "5530" + } + }, + "555 Reparation och underhåll av förbrukningsinventarier": { + "account_type": "Expense Account", + "is_group": 1, + "Reparation och underhåll av förbrukningsinventarier": { + "account_number": "5550" + } + }, + "558 Underhåll och tvätt av arbetskläder": { + "account_type": "Expense Account", + "is_group": 1, + "Underhåll och tvätt av arbetskläder": { + "account_number": "5580" + } + }, + "559 Övriga kostnader för reparation och underhåll": { + "account_type": "Expense Account", + "is_group": 1, + "Övriga kostnader för reparation och underhåll": { + "account_number": "5590" + } + } + }, + "56 Kostnader för transportmedel": { + "is_group": 1, + "560 Kostnader för transportmedel (gruppkonto)": { + "is_group": 1, + "Kostnader för transportmedel (gruppkonto)": { + "account_number": "5600", + "account_type": "Expense Account" + } + }, + "561 Personbilskostnader": { + "is_group": 1, + "Personbilskostnader": { + "account_number": "5610", + "account_type": "Expense Account" + }, + "Drivmedel för personbilar": { + "account_number": "5611", + "account_type": "Expense Account" + }, + "Försäkring och skatt för personbilar": { + "account_number": "5612", + "account_type": "Expense Account" + }, + "Reparation och underhåll av personbilar": { + "account_number": "5613", + "account_type": "Expense Account" + }, + "Leasing av personbilar": { + "account_number": "5615", + "account_type": "Expense Account" + }, + "Trängselskatt, avdragsgill": { + "account_number": "5616", + "account_type": "Expense Account" + }, + "Övriga personbilskostnader": { + "account_number": "5619", + "account_type": "Expense Account" + } + }, + "562 Lastbilkostnader": { + "account_type": "Expense Account", + "is_group": 1, + "Lastbilkostnader": { + "account_number": "5620" + } + }, + "563 Truckkostnader": { + "account_type": "Expense Account", + "is_group": 1, + "Truckkostnader": { + "account_number": "5630" + } + }, + "564 Kostnader för arbetsmaskiner": { + "account_type": "Expense Account", + "is_group": 1, + "Kostnader för arbetsmaskiner": { + "account_number": "5640" + } + }, + "565 Traktorkostnader": { + "account_type": "Expense Account", + "is_group": 1, + "Traktorkostnader": { + "account_number": "5650" + } + }, + "566 Motorcykel-, moped- och skoterkostnade": { + "account_type": "Expense Account", + "is_group": 1, + "Motorcykel-, moped- och skoterkostnade": { + "account_number": "5660" + } + }, + "567 Båt-, flygplans- och helikopterkostnader": { + "account_type": "Expense Account", + "is_group": 1, + "MBåt-, flygplans- och helikopterkostnader": { + "account_number": "5670" + } + }, + "569 Övriga kostnader för transportmedel": { + "account_type": "Expense Account", + "is_group": 1, + "Övriga kostnader för transportmedel": { + "account_number": "5690" + } + } + }, + "57 Frakter och transporter": { + "account_type": "Expense Account", + "is_group": 1, + "570 Frakter och transporter (gruppkonto)": { + "is_group": 1, + "Frakter och transporter (gruppkonto)": { + "account_number": "5700", + "account_type": "Expense Account" + } + }, + "571 Frakter, transporter och försäkringar vid varudistribution": { + "is_group": 1, + "Frakter, transporter och försäkringar vid varudistribution": { + "account_number": "5710" + } + }, + "572 Tull- och speditionskostnader m.m.": { + "is_group": 1, + "Tull- och speditionskostnader m.m.": { + "account_number": "5720" + } + }, + "573 Arbetstransporter": { + "is_group": 1, + "Arbetstransporter": { + "account_number": "5730" + } + }, + "579 Övriga kostnader för frakter och transporter": { + "is_group": 1, + "Övriga kostnader för frakter och transporter": { + "account_number": "5790" + } + } + }, + "58 Resekostnader": { + "account_type": "Expense Account", + "is_group": 1, + "580 Resekostnader (gruppkonto)": { + "is_group": 1, + "Resekostnader (gruppkonto)": { + "account_number": "5800", + "account_type": "Expense Account" + } + }, + "581 Biljetter": { + "is_group": 1, + "Biljetter": { + "account_number": "5810", + "account_type": "Expense Account" + } + }, + "582 Hyrbilskostnader": { + "is_group": 1, + "Hyrbilskostnader": { + "account_number": "5820", + "account_type": "Expense Account" + } + }, + "583 Kost och logi": { + "is_group": 1, + "Kost och logi": { + "account_number": "5830" + }, + "Kost och logi i Sverige": { + "account_number": "5831", + "account_type": "Expense Account" + }, + "Kost och logi i utlandet": { + "account_number": "5832", + "account_type": "Expense Account" + } + }, + "589 Övriga resekostnader": { + "is_group": 1, + "Övriga resekostnader": { + "account_number": "5890" + } + } + }, + "59 Reklam och PR": { + "account_type": "Expense Account", + "is_group": 1, + "590 Reklam och PR (gruppkonto)": { + "is_group": 1, + "Reklam och PR (gruppkonto)": { + "account_number": "5900", + "account_type": "Expense Account" + } + }, + "591 Annonsering": { + "account_type": "Expense Account", + "is_group": 1, + "Annonsering": { + "account_number": "5910" + } + }, + "592 Utomhus- och trafikreklam": { + "account_type": "Expense Account", + "is_group": 1, + "Utomhus- och trafikreklam": { + "account_number": "5920" + } + }, + "593 Reklamtrycksaker och direktreklam": { + "account_type": "Expense Account", + "is_group": 1, + "Reklamtrycksaker och direktreklam": { + "account_number": "5930" + } + }, + "594 Utställningar och mässor": { + "account_type": "Expense Account", + "is_group": 1, + "Utställningar och mässor": { + "account_number": "5940" + } + }, + "595 Butiksreklam och återförsäljarreklam": { + "account_type": "Expense Account", + "is_group": 1, + "Butiksreklam och återförsäljarreklam": { + "account_number": "5950" + } + }, + "596 Varuprover, reklamgåvor, presentreklam och tävlingar": { + "account_type": "Expense Account", + "is_group": 1, + "Varuprover, reklamgåvor, presentreklam och tävlingar": { + "account_number": "5960" + } + }, + "597 Film-, radio-, TV- och Internetreklam": { + "account_type": "Expense Account", + "is_group": 1, + "Film-, radio-, TV- och Internetreklam": { + "account_number": "5970" + } + }, + "598 PR, institutionell reklam och sponsring": { + "account_type": "Expense Account", + "is_group": 1, + "PR, institutionell reklam och sponsring": { + "account_number": "5980" + } + }, + "599 Övriga kostnader för reklam och PR": { + "account_type": "Expense Account", + "is_group": 1, + "Övriga kostnader för reklam och PR": { + "account_number": "5990" + } + } + } + }, + "6 Övriga externa rörelseutgifter/kostnader": { + "root_type": "Expense", + "is_group": 1, + "60 Övriga försäljningskostnader": { + "is_group": 1, + "600 Övriga försäljningskostnader (gruppkonto)": { + "account_type": "Expense Account", + "is_group": 1, + "Övriga försäljningskostnader (gruppkonto)": { + "account_number": "6000" + } + }, + "601 Kataloger, prislistor m.m.": { + "account_type": "Expense Account", + "is_group": 1, + "Kataloger, prislistor m.m.": { + "account_number": "6010" + } + }, + "602 Egna facktidskrifter": { + "account_type": "Expense Account", + "is_group": 1, + "Egna facktidskrifter": { + "account_number": "6020" + } + }, + "603 Speciella orderkostnader": { + "account_type": "Expense Account", + "is_group": 1, + "Speciella orderkostnader": { + "account_number": "6030" + } + }, + "604 Kontokortsavgifter": { + "account_type": "Expense Account", + "is_group": 1, + "Kontokortsavgifter": { + "account_number": "6040" + } + }, + "605 Försäljningsprovisioner": { + "is_group": 1, + "Försäljningsprovisioner": { + "account_number": "6050" + }, + "Franchisekostnader o.dyl.": { + "account_number": "6055" + } + }, + "606 Kreditförsäljningskostnader": { + "is_group": 1, + "Kreditförsäljningskostnader": { + "account_number": "6060" + }, + "Kreditupplysning": { + "account_number": "6061" + }, + "Inkasso och KFM-avgifter": { + "account_number": "6062" + }, + "Kreditförsäkringspremier": { + "account_number": "6063" + }, + "Factoringavgifter": { + "account_number": "6064" + }, + "Övriga kreditförsäljningskostnader": { + "account_number": "6069" + } + }, + "607 Representation": { + "is_group": 1, + "Representation": { + "account_number": "6070" + }, + "Representation, avdragsgill": { + "account_number": "6071", + "account_type": "Expense Account" + }, + "Representation, ej avdragsgill": { + "account_number": "6072", + "account_type": "Expense Account" + } + }, + "608 Bankgarantier": { + "account_type": "Expense Account", + "is_group": 1, + "Bankgarantier": { + "account_number": "6080" + } + }, + "609 Övriga försäljningskostnader": { + "is_group": 1, + "Övriga försäljningskostnader": { + "account_number": "6090", + "account_type": "Expense Account" + } + } + }, + "61 Kontorsmateriel och trycksaker": { + "is_group": 1, + "610 Kontorsmateriel och trycksaker (gruppkonto)": { + "is_group": 1, + "Kontorsmateriel och trycksaker (gruppkonto)": { + "account_number": "6100", + "account_type": "Expense Account" + } + }, + "611 Kontorsmateriel": { + "account_type": "Expense Account", + "is_group": 1, + "Kontorsmateriel": { + "account_number": "6110" + } + }, + "615 Trycksaker": { + "account_type": "Expense Account", + "is_group": 1, + "Trycksaker": { + "account_number": "6150" + } + } + }, + "62 Tele och post": { + "is_group": 1, + "620 Tele och post (gruppkonto)": { + "account_type": "Expense Account", + "is_group": 1, + "Tele och post (gruppkonto)": { + "account_number": "6200" + } + }, + "621 Telekommunikation": { + "account_type": "Expense Account", + "is_group": 1, + "Telekommunikation": { + "account_number": "6210", + "account_type": "Expense Account" + }, + "Fast telefoni": { + "account_number": "6211", + "account_type": "Expense Account" + }, + "Mobiltelefon": { + "account_number": "6212", + "account_type": "Expense Account" + }, + "Mobilsökning": { + "account_number": "6213", + "account_type": "Expense Account" + }, + "Fax": { + "account_number": "6214", + "account_type": "Expense Account" + }, + "Telex": { + "account_number": "6215", + "account_type": "Expense Account" + } + }, + "623 Datakommunikation": { + "account_type": "Expense Account", + "is_group": 1, + "Datakommunikation": { + "account_number": "6230" + } + }, + "625 Postbefordran": { + "is_group": 1, + "Postbefordran": { + "account_number": "6250", + "account_type": "Expense Account" + } + } + }, + "63 Företagsförsäkringar och övriga riskkostnader": { + "is_group": 1, + "630 Företagsförsäkringar och övriga riskkostnader (gruppkonto)": { + "account_type": "Expense Account", + "is_group": 1, + "Företagsförsäkringar och övriga riskkostnader (gruppkonto)": { + "account_number": "6300" + } + }, + "631 Företagsförsäkringar": { + "is_group": 1, + "Företagsförsäkringar": { + "account_number": "6310", + "account_type": "Expense Account" + } + }, + "632 Självrisker vid skada": { + "account_type": "Expense Account", + "is_group": 1, + "Självrisker vid skada": { + "account_number": "6320" + } + }, + "633 Förluster i pågående arbeten": { + "account_type": "Expense Account", + "is_group": 1, + "Förluster i pågående arbeten": { + "account_number": "6330" + } + }, + "634 Lämnade skadestånd": { + "is_group": 1, + "Lämnade skadestånd": { + "account_number": "6340" + }, + "Lämnade skadestånd, avdragsgilla": { + "account_number": "6341" + }, + "Lämnade skadestånd, ej avdragsgilla": { + "account_number": "6342" + } + }, + "635 Förluster på kundfordringar": { + "account_type": "Expense Account", + "is_group": 1, + "Förluster på kundfordringar": { + "account_number": "6350", + "account_type": "Expense Account" + }, + "Konstaterade förluster på kundfordringar": { + "account_number": "6351", + "account_type": "Expense Account" + }, + "Befarade förluster på kundfordringar": { + "account_number": "6352", + "account_type": "Expense Account" + } + }, + "636 Garantikostnader": { + "account_type": "Expense Account", + "is_group": 1, + "Garantikostnader": { + "account_number": "6360" + }, + "Förändring av garantiavsättning": { + "account_number": "6361" + }, + "Faktiska garantikostnader": { + "account_number": "6362" + } + }, + "637 Kostnader för bevakning och larm": { + "account_type": "Expense Account", + "is_group": 1, + "Kostnader för bevakning och larm": { + "account_number": "6370" + } + }, + "638 Förluster på övriga kortfristiga fordringar": { + "account_type": "Expense Account", + "is_group": 1, + "Förluster på övriga kortfristiga fordringar": { + "account_number": "6380" + } + }, + "639 Övriga riskkostnader": { + "is_group": 1, + "Övriga riskkostnader": { + "account_number": "6390", + "account_type": "Expense Account" + } + } + }, + "64 Förvaltningskostnader": { + "is_group": 1, + "640 Förvaltningskostnader (gruppkonto)": { + "account_type": "Expense Account", + "is_group": 1, + "Förvaltningskostnader (gruppkonto)": { + "account_number": "6400" + } + }, + "641 Styrelsearvoden som inte är lön": { + "is_group": 1, + "Styrelsearvoden som inte är lön": { + "account_number": "6410", + "account_type": "Expense Account" + } + }, + "642 Ersättningar till revisor": { + "account_type": "Expense Account", + "is_group": 1, + "Ersättningar till revisor": { + "account_number": "6420", + "account_type": "Expense Account" + }, + "Revision": { + "account_number": "6421", + "account_type": "Expense Account" + }, + "Revisonsverksamhet utöver revision": { + "account_number": "6422", + "account_type": "Expense Account" + }, + "Skatterådgivning – revisor": { + "account_number": "6423", + "account_type": "Expense Account" + }, + "Övriga tjänster – revisor": { + "account_number": "6424", + "account_type": "Expense Account" + } + }, + "643 Management fees": { + "account_type": "Expense Account", + "is_group": 1, + "Management fees": { + "account_number": "6430" + } + }, + "644 Årsredovisning och delårsrapporter": { + "account_type": "Expense Account", + "is_group": 1, + "Årsredovisning och delårsrapporter": { + "account_number": "6440" + } + }, + "645 Bolagsstämma/års- eller föreningsstämma": { + "account_type": "Expense Account", + "is_group": 1, + "Bolagsstämma/års- eller föreningsstämma": { + "account_number": "6450" + } + }, + "649 Övriga förvaltningskostnader": { + "account_type": "Expense Account", + "is_group": 1, + "Övriga förvaltningskostnader": { + "account_number": "6490" + } + } + }, + "65 Övriga externa tjänster": { + "is_group": 1, + "650 Övriga externa tjänster (gruppkonto)": { + "account_type": "Expense Account", + "is_group": 1, + "Övriga externa tjänster (gruppkonto)": { + "account_number": "6500" + } + }, + "651 Mätningskostnader": { + "account_type": "Expense Account", + "is_group": 1, + "Mätningskostnader": { + "account_number": "6510" + } + }, + "652 Ritnings- och kopieringskostnader": { + "account_type": "Expense Account", + "is_group": 1, + "Ritnings- och kopieringskostnader": { + "account_number": "6520" + } + }, + "653 Redovisningstjänster": { + "is_group": 1, + "Redovisningstjänster": { + "account_number": "6530", + "account_type": "Expense Account" + } + }, + "654 IT-tjänster": { + "is_group": 1, + "IT-tjänster": { + "account_number": "6540", + "account_type": "Expense Account" + } + }, + "655 Konsultarvoden": { + "account_type": "Expense Account", + "is_group": 1, + "Konsultarvoden": { + "account_number": "6550", + "account_type": "Expense Account" + }, + "Arkitekttjänster": { + "account_number": "6551", + "account_type": "Expense Account" + }, + "Teknisk provning och analys": { + "account_number": "6552", + "account_type": "Expense Account" + }, + "Tekniska konsulttjänster": { + "account_number": "6553", + "account_type": "Expense Account" + }, + "Finansiell- och övrig ekonomisk rådgivning": { + "account_number": "6554", + "account_type": "Expense Account" + }, + "Skatterådgivning inkl. insolvens- och konkursförvaltning": { + "account_number": "6555", + "account_type": "Expense Account" + }, + "Köpta tjänster avseende forskning och utveckling": { + "account_number": "6556", + "account_type": "Expense Account" + }, + "Övrig konsultverksamhet": { + "account_number": "6559", + "account_type": "Expense Account" + } + }, + "656 Serviceavgifter till branschorganisationer": { + "is_group": 1, + "Serviceavgifter till branschorganisationer": { + "account_number": "6560", + "account_type": "Expense Account" + } + }, + "657 Bankkostnader": { + "is_group": 1, + "Bankkostnader": { + "account_number": "6570", + "account_type": "Expense Account" + } + }, + "658 Advokat- och rättegångskostnader": { + "account_type": "Expense Account", + "is_group": 1, + "Advokat- och rättegångskostnader": { + "account_number": "6580" + } + }, + "659 Övriga externa tjänster": { + "is_group": 1, + "Övriga externa tjänster": { + "account_number": "6590", + "account_type": "Expense Account" + } + } + }, + "66 (Fri kontogrupp)": { + "account_type": "Expense Account", + "is_group": 1, + "660 (Fri kontogrupp)": { + "account_type": "Expense Account", + "is_group": 1, + "(Fri kontogrupp)": { + "account_number": "6600" + } + } + }, + "67 (Fri kontogrupp)": { + "account_type": "Expense Account", + "is_group": 1, + "670 (Fri kontogrupp)": { + "account_type": "Expense Account", + "is_group": 1, + "(Fri kontogrupp)": { + "account_number": "6700" + } + } + }, + "68 Inhyrd personal": { + "is_group": 1, + "680 Inhyrd personal (gruppkonto)": { + "is_group": 1, + "Inhyrd personal (gruppkonto)": { + "account_number": "6800", + "account_type": "Expense Account" + } + }, + "681 Inhyrd produktionspersonal": { + "account_type": "Expense Account", + "is_group": 1, + "Inhyrd produktionspersonal": { + "account_number": "6810" + } + }, + "682 Inhyrd lagerpersonal": { + "account_type": "Expense Account", + "is_group": 1, + "Inhyrd lagerpersonal": { + "account_number": "6820" + } + }, + "683 Inhyrd transportpersonal": { + "account_type": "Expense Account", + "is_group": 1, + "Inhyrd transportpersonal": { + "account_number": "6830" + } + }, + "684 Inhyrd kontors- och ekonomipersonal": { + "account_type": "Expense Account", + "is_group": 1, + "Inhyrd kontors- och ekonomipersonal": { + "account_number": "6840" + } + }, + "685 Inhyrd IT-personal": { + "account_type": "Expense Account", + "is_group": 1, + "Inhyrd IT-personal": { + "account_number": "6850" + } + }, + "686 Inhyrd marknads- och försäljningspersonal": { + "account_type": "Expense Account", + "is_group": 1, + "Inhyrd marknads- och försäljningspersonal": { + "account_number": "6860" + } + }, + "687 Inhyrd restaurang- och butikspersonal": { + "account_type": "Expense Account", + "is_group": 1, + "Inhyrd restaurang- och butikspersonal": { + "account_number": "6870" + } + }, + "688 Inhyrda företagsledare": { + "account_type": "Expense Account", + "is_group": 1, + "Inhyrda företagsledare": { + "account_number": "6880" + } + }, + "689 Övrig inhyrd personal": { + "account_type": "Expense Account", + "is_group": 1, + "Övrig inhyrd personal": { + "account_number": "6890" + } + } + }, + "69 Övriga externa kostnader": { + "is_group": 1, + "690 Övriga externa kostnader (gruppkonto)": { + "account_type": "Expense Account", + "is_group": 1, + "Övriga externa kostnader (gruppkonto)": { + "account_number": "6900" + } + }, + "691 Licensavgifter och royalties": { + "account_type": "Expense Account", + "is_group": 1, + "Licensavgifter och royalties": { + "account_number": "6910" + } + }, + "692 Kostnader för egna patent": { + "account_type": "Expense Account", + "is_group": 1, + "Kostnader för egna patent": { + "account_number": "6920" + } + }, + "693 Kostnader för varumärken m.m.": { + "account_type": "Expense Account", + "is_group": 1, + "Kostnader för varumärken m.m.": { + "account_number": "6930" + } + }, + "694 Kontroll-, provnings- och stämpelavgifter": { + "account_type": "Expense Account", + "is_group": 1, + "Kontroll-, provnings- och stämpelavgifter": { + "account_number": "6940" + } + }, + "695 Tillsynsavgifter myndigheter": { + "account_type": "Expense Account", + "is_group": 1, + "Tillsynsavgifter myndigheter": { + "account_number": "6950" + } + }, + "697 Tidningar, tidskrifter och facklitteratur": { + "is_group": 1, + "Tidningar, tidskrifter och facklitteratur": { + "account_number": "6970", + "account_type": "Expense Account" + } + }, + "698 Föreningsavgifter": { + "is_group": 1, + "Föreningsavgifter": { + "account_number": "6980", + "account_type": "Expense Account" + }, + "Föreningsavgifter, avdragsgilla": { + "account_number": "6981" + }, + "Föreningsavgifter,ej avdragsgilla": { + "account_number": "6982" + } + }, + "699 Övriga externa kostnader": { + "is_group": 1, + "Övriga externa kostnader": { + "account_number": "6990" + }, + "Övriga externa kostnader, avdragsgilla": { + "account_number": "6991", + "account_type": "Expense Account" + }, + "Övriga externa kostnader, ej avdragsgilla": { + "account_number": "6992", + "account_type": "Expense Account" + }, + "Lämnade bidrag och gåvor": { + "account_number": "6993" + }, + "Betald utländsk inkomstskatt": { + "account_number": "6996" + }, + "Obetald utländsk inkomstskatt": { + "account_number": "6997" + }, + "Utländsk moms": { + "account_number": "6998" + }, + "Ingående moms, blandad verksamhet": { + "account_number": "6999" + } + } + } + }, + "7 Utgifter/kostnader för personal, avskrivningar m.m.": { + "root_type": "Expense", + "is_group": 1, + "70 Löner till kollektivanställda": { + "is_group": 1, + "700 Löner till kollektivanställda (gruppkonto)": { + "account_type": "Expense Account", + "is_group": 1, + "Löner till kollektivanställda (gruppkonto)": { + "account_number": "7000" + } + }, + "701 Löner till kollektivanställda": { + "is_group": 1, + "Löner till kollektivanställda": { + "account_number": "7010", + "account_type": "Expense Account" + }, + "Löner till kollektivanställda övriga": { + "account_number": "7011", + "account_type": "Expense Account" + }, + "Vinstandelar till kollektivanställda": { + "account_number": "7012" + }, + "Lön växa-stöd kollektivanställda 10,21 %": { + "account_number": "7013" + }, + "Avgångsvederlag till kollektivanställda": { + "account_number": "7017" + }, + "Bruttolöneavdrag, kollektivanställda": { + "account_number": "7018" + }, + "Upplupna löner och vinstandelar till kollektivanställda": { + "account_number": "7019" + } + }, + "703 Löner till kollektivanställda (utlandsanställda)": { + "is_group": 1, + "Löner till kollektivanställda (utlandsanställda)": { + "account_number": "7030" + }, + "Löner till kollektivanställda (utlandsanställda) övriga": { + "account_number": "7031" + }, + "Vinstandelar till kollektivanställda (utlandsanställda)": { + "account_number": "7032" + }, + "Avgångsvederlag till kollektivanställda (utlandsanställda)": { + "account_number": "7037" + }, + "Bruttolöneavdrag, kollektivanställda (utlandsanställda)": { + "account_number": "7038" + }, + "Upplupna löner och vinstandelar till kollektivanställda (utlandsanställda)": { + "account_number": "7039" + } + }, + "708 Löner till kollektivanställda för ej arbetad tid": { + "is_group": 1, + "Löner till kollektivanställda för ej arbetad tid": { + "account_number": "7080" + }, + "Sjuklöner till kollektivanställda": { + "account_number": "7081" + }, + "Semesterlöner till kollektivanställda": { + "account_number": "7082" + }, + "Föräldraersättning till kollektivanställda": { + "account_number": "7083" + }, + "Övriga löner till kollektivanställda för ej arbetad tid": { + "account_number": "7089" + } + }, + "709 Förändring av semesterlöneskuld": { + "is_group": 1, + "Förändring av semesterlöneskuld": { + "account_number": "7090", + "account_type": "Expense Account" + } + } + }, + "71 (Fri kontogrupp)": { + "account_type": "Expense Account", + "is_group": 1, + "710 (Fri kontogrupp)": { + "account_type": "Expense Account", + "is_group": 1, + "(Fri kontogrupp)": { + "account_number": "7100" + } + } + }, + "72 Löner till tjänstemän och företagsledare": { + "is_group": 1, + "720 Löner till tjänstemän och företagsledare (gruppkonto)": { + "account_type": "Expense Account", + "Löner till tjänstemän och företagsledare (gruppkonto)": { + "account_number": "7200" + } + }, + "721 Löner till tjänstemän": { + "is_group": 1, + "Löner till tjänstemän": { + "account_number": "7210", + "account_type": "Expense Account" + }, + "Vinstandelar till tjänstemän": { + "account_number": "7212" + }, + "Lön växa-stöd tjänstemän 10,21 %": { + "account_number": "7213" + }, + "Avgångsvederlag till tjänstemän": { + "account_number": "7217" + }, + "Bruttolöneavdrag, tjänstemän": { + "account_number": "7218" + }, + "Upplupna löner och vinstandelar till tjänstemän": { + "account_number": "7219" + } + }, + "722 Löner till företagsledare": { + "is_group": 1, + "Löner till företagsledare": { + "account_number": "7220", + "account_type": "Expense Account" + }, + "Löner till företagsledare övriga": { + "account_number": "7221" + }, + "Tantiem till företagsledare": { + "account_number": "7222" + }, + "Avgångsvederlag till företagsledare": { + "account_number": "7227" + }, + "Bruttolöneavdrag, företagsledare": { + "account_number": "7228" + }, + "Upplupna löner och tantiem till företagsledare": { + "account_number": "7229" + } + }, + "723 Löner till tjänstemän och ftgsledare (utlandsanställda)": { + "is_group": 1, + "Löner till tjänstemän och ftgsledare (utlandsanställda)": { + "account_number": "7230" + }, + "Löner till tjänstemän och ftgsledare övriga (utlandsanställda)": { + "account_number": "7231" + }, + "Vinstandelar till tjänstemän och ftgsledare (utlandsanställda)": { + "account_number": "7232" + }, + "Avgångsvederlag till tjänstemän och ftgsledare (utlandsanställda)": { + "account_number": "7237" + }, + "Bruttolöneavdrag, tjänstemän och ftgsledare (utlandsanställda)": { + "account_number": "7238" + }, + "Upplupna löner och vinstandelar till tjänstemän och ftgsledare (utlandsanställda)": { + "account_number": "7239" + } + }, + "724 Styrelsearvoden": { + "is_group": 1, + "Styrelsearvoden": { + "account_number": "7240", + "account_type": "Expense Account" + } + }, + "728 Löner till tjänstemän och företagsledare för ej arbetad tid": { + "is_group": 1, + "Löner till tjänstemän och företagsledare för ej arbetad tid": { + "account_number": "7280" + }, + "Sjuklöner till tjänstemän": { + "account_number": "7281" + }, + "Sjuklöner till företagsledare": { + "account_number": "7282" + }, + "Föräldraersättning till tjänstemän": { + "account_number": "7283" + }, + "Föräldraersättning till företagsledare": { + "account_number": "7284" + }, + "Semesterlöner till tjänstemän": { + "account_number": "7285" + }, + "Semesterlöner till företagsledare": { + "account_number": "7286" + }, + "Övriga löner till tjänstemän för ej arbetad tid": { + "account_number": "7288" + }, + "Övriga löner till företagsledare för ej arbetad tid": { + "account_number": "7289" + } + }, + "729 Förändring av semesterlöneskuld": { + "account_type": "Expense Account", + "is_group": 1, + "Förändring av semesterlöneskuld": { + "account_number": "7290", + "account_type": "Expense Account" + }, + "Förändring av semesterlöneskuld till tjänstemän": { + "account_number": "7291" + }, + "Förändring av semesterlöneskuld till företagsledare": { + "account_number": "7292" + } + } + }, + "73 Kostnadsersättningar och förmåner": { + "is_group": 1, + "730 Kostnadsersättningar och förmåner (gruppkonto)": { + "account_type": "Expense Account", + "is_group": 1, + "Kostnadsersättningar och förmåner (gruppkonto)": { + "account_number": "7300" + } + }, + "731 Kontanta extraersättningar": { + "is_group": 1, + "Kontanta extraersättningar": { + "account_number": "7310", + "account_type": "Expense Account" + }, + "Ersättningar för sammanträden m.m.": { + "account_number": "7311" + }, + "Ersättningar för förslagsverksamhet och uppfinningar": { + "account_number": "7312" + }, + "Ersättningar för/bidrag till bostadskostnader": { + "account_number": "7313" + }, + "Ersättningar för/bidrag till måltidskostnader": { + "account_number": "7314" + }, + "Ersättningar för/bidrag till resor till och från arbetsplatsen": { + "account_number": "7315" + }, + "Ersättningar för/bidrag till arbetskläder": { + "account_number": "7316" + }, + "Ersättningar för/bidrag till arbetsmaterial och arbetsverktyg": { + "account_number": "7317" + }, + "Felräkningspengar": { + "account_number": "7318" + }, + "Övriga kontanta extraersättningar": { + "account_number": "7319" + } + }, + "732 Traktamenten vid tjänsteresa": { + "is_group": 1, + "Traktamenten vid tjänsteresa": { + "account_number": "7320" + }, + "Skattefria traktamenten, Sverige": { + "account_number": "7321", + "account_type": "Expense Account" + }, + "Skattepliktiga traktamenten, Sverige": { + "account_number": "7322", + "account_type": "Expense Account" + }, + "Skattefria traktamenten, utlandet": { + "account_number": "7323", + "account_type": "Expense Account" + }, + "Skattepliktiga traktamenten, utlandet": { + "account_number": "7324", + "account_type": "Expense Account" + } + }, + "733 Bilersättningar": { + "is_group": 1, + "Bilersättningar": { + "account_number": "7330" + }, + "Skattefria bilersättningar": { + "account_number": "7331", + "account_type": "Expense Account" + }, + "Skattepliktiga bilersättningar": { + "account_number": "7332", + "account_type": "Expense Account" + }, + "Ersättning för trängselskatt, skattefri": { + "account_number": "7333", + "account_type": "Expense Account" + } + }, + "735 Ersättningar för föreskrivna arbetskläder": { + "account_type": "Expense Account", + "is_group": 1, + "Ersättningar för föreskrivna arbetskläder": { + "account_number": "7350" + } + }, + "737 Representationsersättningar": { + "account_type": "Expense Account", + "is_group": 1, + "Representationsersättningar": { + "account_number": "7370" + } + }, + "738 Kostnader för förmåner till anställda": { + "is_group": 1, + "Kostnader för förmåner till anställda": { + "account_number": "7380", + "account_type": "Expense Account" + }, + "Kostnader för fri bostad": { + "account_number": "7381" + }, + "Kostnader för fria eller subventionerade måltider": { + "account_number": "7382" + }, + "Kostnader för fria resor till och från arbetsplatsen": { + "account_number": "7383" + }, + "Kostnader för fria eller subventionerade arbetskläder": { + "account_number": "7384" + }, + "Kostnader för fri bil": { + "account_number": "7385", + "account_type": "Expense Account" + }, + "Subventionerad ränta": { + "account_number": "7386" + }, + "Kostnader för lånedatorer": { + "account_number": "7387" + }, + "Anställdas ersättning för erhållna förmåner": { + "account_number": "7388" + }, + "Övriga kostnader för förmåner": { + "account_number": "7389" + } + }, + "739 Övriga kostnadsersättningar och förmåner": { + "is_group": 1, + "Övriga kostnadsersättningar och förmåner": { + "account_number": "7390", + "account_type": "Expense Account" + }, + "Kostnad för trängselskatteförmån": { + "account_number": "7391" + }, + "Kostnad för förmån av hushållsnära tjänster": { + "account_number": "7392" + } + } + }, + "74 Löner till tjänstemän och företagsledare": { + "is_group": 1, + "740 Pensionskostnader (gruppkonto)": { + "account_type": "Expense Account", + "is_group": 1, + "Pensionskostnader (gruppkonto)": { + "account_number": "7400" + } + }, + "741 Pensionsförsäkringspremier": { + "is_group": 1, + "Pensionsförsäkringspremier": { + "account_number": "7410", + "account_type": "Expense Account" + }, + "Premier för kollektiva pensionsförsäkringar": { + "account_number": "7411" + }, + "Premier för individuella pensionsförsäkringar": { + "account_number": "7412" + } + }, + "742 Förändring av pensionsskuld": { + "account_type": "Expense Account", + "is_group": 1, + "Förändring av pensionsskuld": { + "account_number": "7420" + } + }, + "743 Avdrag för räntedel i pensionskostnad": { + "account_type": "Expense Account", + "is_group": 1, + "Avdrag för räntedel i pensionskostnad": { + "account_number": "7430" + } + }, + "744 Förändring av pensionsstiftelsekapital": { + "is_group": 1, + "Förändring av pensionsstiftelsekapital": { + "account_number": "7440" + }, + "Överföring av medel till pensionsstiftelse": { + "account_number": "7441" + }, + "Gottgörelse från pensionsstiftelse": { + "account_number": "7448" + } + }, + "746 Pensionsutbetalningar": { + "is_group": 1, + "Pensionsutbetalningar": { + "account_number": "7460" + }, + "Pensionsutbetalningar till f.d. kollektivanställda": { + "account_number": "7461" + }, + "Pensionsutbetalningar till f.d. tjänstemän": { + "account_number": "7462" + }, + "Pensionsutbetalningar till f.d. företagsledare": { + "account_number": "7463" + } + }, + "747 Förvaltnings- och kreditförsäkringsavgifter": { + "account_type": "Expense Account", + "is_group": 1, + "Förvaltnings- och kreditförsäkringsavgifter": { + "account_number": "7470" + } + }, + "749 Övriga pensionskostnader": { + "is_group": 1, + "Övriga pensionskostnader": { + "account_number": "7490", + "account_type": "Expense Account" + } + } + }, + "75 Sociala och andra avgifter enligt lag och avtal": { + "is_group": 1, + "750 Sociala och andra avgifter enligt lag och avtal (gruppkonto)": { + "account_type": "Expense Account", + "is_group": 1, + "Sociala och andra avgifter enligt lag och avtal (gruppkonto)": { + "account_number": "7500" + } + }, + "751 Arbetsgivaravgifter 31,42 %": { + "is_group": 1, + "Arbetsgivaravgifter 31,42 %": { + "account_number": "7510" + }, + "Arbetsgivaravgifter för löner och ersättningar": { + "account_number": "7511", + "account_type": "Expense Account" + }, + "Arbetsgivaravgifter för förmånsvärden": { + "account_number": "7512", + "account_type": "Expense Account" + }, + "Arbetsgivaravgifter på skattepliktiga kostnadsersättningar": { + "account_number": "7515" + }, + "Arbetsgivaravgifter på arvoden": { + "account_number": "7516" + }, + "Arbetsgivaravgifter på bruttolöneavdrag m.m.": { + "account_number": "7518" + }, + "Arbetsgivaravgifter för semester- och löneskulder": { + "account_number": "7519", + "account_type": "Expense Account" + } + }, + "753 Särskild löneskatt": { + "is_group": 1, + "Särskild löneskatt": { + "account_number": "7530", + "account_type": "Expense Account" + }, + "Särskild löneskatt för vissa försäkringsersättningar m.m.": { + "account_number": "7531" + }, + "Särskild löneskatt pensionskostnader, deklarationspost": { + "account_number": "7532" + }, + "Särskild löneskatt för pensionskostnader": { + "account_number": "7533" + } + }, + "755 Avkastningsskatt på pensionsmedel": { + "is_group": 1, + "Avkastningsskatt på pensionsmedel": { + "account_number": "7550", + "account_type": "Expense Account" + }, + "Avkastningsskatt 15 % försäkringsföretag m.fl. samt avsatt till pensioner": { + "account_number": "7551" + }, + "Avkastningsskatt 15 % utländska pensionsförsäkringar": { + "account_number": "7552" + }, + "Avkastningsskatt 30 % utländska försäkringsföretag m.fl.": { + "account_number": "7553" + }, + "Avkastningsskatt 30 % utländska kapitalförsäkringar": { + "account_number": "7554" + } + }, + "757 Premier för arbetsmarknadsförsäkringar": { + "is_group": 1, + "Premier för arbetsmarknadsförsäkringar": { + "account_number": "7570", + "account_type": "Expense Account" + }, + "Arbetsmarknadsförsäkringar": { + "account_number": "7571" + }, + "Arbetsmarknadsförsäkringar pensionsförsäkringspremier, deklarationspost": { + "account_number": "7572" + } + }, + "758 Gruppförsäkringspremier": { + "is_group": 1, + "Gruppförsäkringspremier": { + "account_number": "7580", + "account_type": "Expense Account" + }, + "Grupplivförsäkringspremier": { + "account_number": "7581" + }, + "Gruppsjukförsäkringspremier": { + "account_number": "7582" + }, + "Gruppolycksfallsförsäkringspremier": { + "account_number": "7583" + }, + "Övriga gruppförsäkringspremier": { + "account_number": "7589" + } + }, + "759 Övriga sociala och andra avgifter enligt lag och avtal": { + "is_group": 1, + "Övriga sociala och andra avgifter enligt lag och avtal": { + "account_number": "7590", + "account_type": "Expense Account" + } + } + }, + "76 Övriga personalkostnader": { + "is_group": 1, + "760 Övriga personalkostnader (gruppkonto)": { + "is_group": 1, + "Övriga personalkostnader (gruppkonto)": { + "account_number": "7600", + "account_type": "Expense Account" + } + }, + "761 Utbildning": { + "is_group": 1, + "Utbildning": { + "account_number": "7610", + "account_type": "Expense Account" + } + }, + "762 Sjuk- och hälsovård": { + "is_group": 1, + "Sjuk- och hälsovård": { + "account_number": "7620" + }, + "Sjuk- och hälsovård, avdragsgill": { + "account_number": "7621", + "account_type": "Expense Account" + }, + "Sjuk- och hälsovård, ej avdragsgill": { + "account_number": "7622", + "account_type": "Expense Account" + }, + "Sjukvårdsförsäkring, ej avdragsgill": { + "account_number": "7623" + } + }, + "763 Personalrepresentation": { + "is_group": 1, + "Personalrepresentation": { + "account_number": "7630" + }, + "Personalrepresentation, avdragsgill": { + "account_number": "7631", + "account_type": "Expense Account" + }, + "Personalrepresentation, ej avdragsgill": { + "account_number": "7632", + "account_type": "Expense Account" + } + }, + "765 Sjuklöneförsäkring": { + "account_type": "Expense Account", + "is_group": 1, + "Sjuklöneförsäkring": { + "account_number": "7650" + } + }, + "767 Förändring av personalstiftelsekapital": { + "is_group": 1, + "Förändring av personalstiftelsekapital": { + "account_number": "7670" + }, + "Avsättning till personalstiftelse": { + "account_number": "7671" + }, + "Gottgörelse från personalstiftelse": { + "account_number": "7678" + } + }, + "769 Övrig personalkostnad": { + "is_group": 1, + "Övriga personalkostnader": { + "account_number": "7690" + }, + "Personalrekrytering": { + "account_number": "7691" + }, + "Begravningshjälp": { + "account_number": "7692" + }, + "Fritidsverksamhet": { + "account_number": "7693" + }, + "Övriga personalkostnader övriga": { + "account_number": "7699" + } + } + }, + "77 Nedskrivningar och återföring av nedskrivningar": { + "is_group": 1, + "771 Nedskrivningar av immateriella anläggningstillgångar": { + "account_type": "Expense Account", + "is_group": 1, + "Nedskrivningar av immateriella anläggningstillgångar": { + "account_number": "7710" + } + }, + "772 Nedskrivningar av byggnader och mark": { + "is_group": 1, + "Nedskrivningar av byggnader och mark": { + "account_number": "7720", + "account_type": "Expense Account" + } + }, + "773 Nedskrivningar av maskiner och inventarier": { + "is_group": 1, + "Nedskrivningar av maskiner och inventarier": { + "account_number": "7730", + "account_type": "Expense Account" + } + }, + "774 Nedskrivningar av vissa omsättningstillgångar": { + "account_type": "Expense Account", + "is_group": 1, + "Nedskrivningar av vissa omsättningstillgångar": { + "account_number": "7740" + } + }, + "776 Återföring av nedskrivningar av immateriella anläggningstillgångar": { + "account_type": "Expense Account", + "is_group": 1, + "Återföring av nedskrivningar av immateriella anläggningstillgångar": { + "account_number": "7760" + } + }, + "777 Återföring av nedskrivningar av byggnader och mark": { + "account_type": "Expense Account", + "is_group": 1, + "Återföring av nedskrivningar av byggnader och mark": { + "account_number": "7770" + } + }, + "778 Återföring av nedskrivningar av maskiner och inventarier": { + "account_type": "Expense Account", + "is_group": 1, + "Återföring av nedskrivningar av maskiner och inventarier": { + "account_number": "7780" + } + }, + "779 Återföring av nedskrivningar av vissa omsättningstillgångar": { + "account_type": "Expense Account", + "is_group": 1, + "Återföring av nedskrivningar av vissa omsättningstillgångar": { + "account_number": "7790" + } + } + }, + "78 Avskrivningar enligt plan": { + "is_group": 1, + "781 Avskrivningar på immateriella anläggningstillgångar": { + "is_group": 1, + "Avskrivningar på immateriella anläggningstillgångar": { + "account_number": "7810", + "account_type": "Depreciation" + }, + "Avskrivningar på balanserade utgifter": { + "account_number": "7811" + }, + "Avskrivningar på patent": { + "account_number": "7813" + }, + "Avskrivningar på licenser": { + "account_number": "7814" + }, + "Avskrivningar på hyresrätter": { + "account_number": "7816" + }, + "Avskrivningar på goodwill": { + "account_number": "7817" + }, + "Avskrivningar på övriga immateriella anläggningstillgångar": { + "account_number": "7819", + "account_type": "Depreciation" + } + }, + "782 Avskrivningar på byggnader och markanläggningar": { + "is_group": 1, + "Avskrivningar på byggnader och markanläggningar": { + "account_number": "7820", + "account_type": "Expense Account" + }, + "Avskrivningar på byggnader": { + "account_number": "7821" + }, + "Avskrivningar på markanläggningar": { + "account_number": "7824" + }, + "Avskrivningar på övriga byggnader": { + "account_number": "7829" + } + }, + "783 Avskrivningar på maskiner och inventarier": { + "is_group": 1, + "Avskrivningar på maskiner och inventarier": { + "account_number": "7830", + "account_type": "Depreciation" + }, + "Avskrivningar på maskiner och andra tekniska anläggningar": { + "account_number": "7831", + "account_type": "Depreciation" + }, + "Avskrivningar på inventarier och verktyg": { + "account_number": "7832", + "account_type": "Depreciation" + }, + "Avskrivningar på installationer": { + "account_number": "7833", + "account_type": "Depreciation" + }, + "Avskrivningar på bilar och andra transportmedel": { + "account_number": "7834", + "account_type": "Depreciation" + }, + "Avskrivningar på datorer": { + "account_number": "7835", + "account_type": "Depreciation" + }, + "Avskrivningar på leasade tillgångar": { + "account_number": "7836", + "account_type": "Depreciation" + }, + "Avskrivningar på övriga maskiner och inventarier": { + "account_number": "7839", + "account_type": "Depreciation" + } + }, + "784 Avskrivningar på förbättringsutgifter på annans fastighet": { + "is_group": 1, + "Avskrivningar på förbättringsutgifter på annans fastighet": { + "account_number": "7840" + } + } + }, + "79 Övriga rörelsekostnader": { + "is_group": 1, + "794 Orealiserade positiva/negativa värdeförändringar på säkringsinstrument": { + "account_type": "Expense Account", + "is_group": 1, + "Orealiserade positiva/negativa värdeförändringar på säkringsinstrument": { + "account_number": "7940" + } + }, + "796 Valutakursförluster på fordringar och skulder av rörelsekaraktär": { + "account_type": "Expense Account", + "is_group": 1, + "Valutakursförluster på fordringar och skulder av rörelsekaraktär": { + "account_number": "7960" + } + }, + "797 Förlust vid avyttring av immateriella och materiella anläggningstillgångar": { + "is_group": 1, + "Förlust vid avyttring av immateriella och materiella anläggningstillgångar": { + "account_number": "7970", + "account_type": "Expense Account" + }, + "Förlust vid avyttring av immateriella anläggningstillgångar": { + "account_number": "7971" + }, + "Förlust vid avyttring av byggnader och mark": { + "account_number": "7972" + }, + "Förlust vid avyttring av maskiner och inventarier": { + "account_number": "7973" + } + }, + "799 Övriga rörelsekostnader": { + "is_group": 1, + "Övriga rörelsekostnader": { + "account_number": "7999", + "account_type": "Expense Account" + } + } + } + }, + "8 Finansiella och andra inkomster/intäkter och utgifter/kostnader": { + "root_type": "Expense", + "is_group": 1, + "80 Resultat från andelar i koncernföretag": { + "is_group": 1, + "801 Utdelning på andelar i koncernföretag": { + "is_group": 1, + "Utdelning på andelar i koncernföretag": { + "account_number": "8010" + }, + "Utdelning på andelar i dotterföretag": { + "account_number": "8012" + }, + "Emissionsinsats, koncernföretag": { + "account_number": "8016" + } + }, + "802 Resultat vid försäljning av andelar i koncernföretag": { + "is_group": 1, + "Resultat vid försäljning av andelar i koncernföretag": { + "account_number": "8020" + }, + "Resultat vid försäljning av andelar i dotterföretag": { + "account_number": "8022" + } + }, + "803 Resultatandelar från handelsbolag (dotterföretag)": { + "is_group": 1, + "Resultatandelar från handelsbolag (dotterföretag)": { + "account_number": "8030" + } + }, + "807 Nedskrivningar av andelar i och långfristiga fordringar hos koncernföretag": { + "is_group": 1, + "Nedskrivningar av andelar i och långfristiga fordringar hos koncernföretag": { + "account_number": "8070" + }, + "Nedskrivningar av andelar i dotterföretag": { + "account_number": "8072" + }, + "Nedskrivningar av långfristiga fordringar hos moderföretag": { + "account_number": "8076" + }, + "Nedskrivningar av långfristiga fordringar hos dotterföretag": { + "account_number": "8077" + } + }, + "808 återföringar av nedskrivningar av andelar i och långfristiga fordringar hos koncernföretag": { + "is_group": 1, + "återföringar av nedskrivningar av andelar i och långfristiga fordringar hos koncernföretag": { + "account_number": "8080" + }, + "återföringar av nedskrivningar av andelar i dotterföretag": { + "account_number": "8082" + }, + "återföringar av nedskrivningar av långfristiga fordringar hos moderföretag": { + "account_number": "8086" + }, + "återföringar av nedskrivningar av långfristiga fordringar hos dotterföretag": { + "account_number": "8087" + } + } + }, + "81 Resultat från andelar i intresseföretag": { + "account_type": "Expense Account", + "is_group": 1, + "811 Utdelningar på andelar i intresseföretag": { + "account_type": "Expense Account", + "is_group": 1, + "Utdelningar på andelar i intresseföretag": { + "account_number": "8110" + }, + "Utdelningar på andelar i intresseföretag övriga": { + "account_number": "8111" + }, + "Utdelningar på andelar i gemensamt styrda företag": { + "account_number": "8112" + }, + "Utdelningar på andelar i övriga företag": { + "account_number": "8113" + }, + "Emissionsinsats, intresseföretag": { + "account_number": "8116" + }, + "Emissionsinsats, gemensamt styrda företag": { + "account_number": "8117" + }, + "Emissionsinsats, övriga företag": { + "account_number": "8118" + } + }, + "812 Resultat vid försäljning av andelar i intresseföretag": { + "account_type": "Expense Account", + "is_group": 1, + "Resultat vid försäljning av andelar i intresseföretag": { + "account_number": "8120" + }, + "Resultat vid försäljning av andelar i intresseföretag övriga": { + "account_number": "8121" + }, + "Resultat vid försäljning av andelar i gemensamt styrda företag": { + "account_number": "8122" + }, + "Resultat vid försäljning av andelar i övriga företag": { + "account_number": "8123" + } + }, + "813 Resultatandelar från handelsbolag": { + "account_type": "Expense Account", + "is_group": 1, + "Resultatandelar från handelsbolag (intresseföretag, gemensamt styrda företag)": { + "account_number": "8130" + }, + "Resultatandelar från handelsbolag (intresseföretag)": { + "account_number": "8131" + }, + "Resultatandelar från handelsbolag (gemensamt styrda företag)": { + "account_number": "8132" + }, + "Resultatandelar från handelsbolag (övriga företag)": { + "account_number": "8133" + } + }, + "817 Nedskrivningar av andelar i och långfristiga fordringar hos intresseföretag": { + "account_type": "Expense Account", + "is_group": 1, + "Nedskrivningar av andelar i och långfristiga fordringar hos intresseföretag": { + "account_number": "8170" + }, + "Nedskrivningar av andelar i intresseföretag": { + "account_number": "8171" + }, + "Nedskrivningar av långfristiga fordringar hos intresseföretag": { + "account_number": "8172" + }, + "Nedskrivningar av andelar i gemensamt styrda företag": { + "account_number": "8173" + }, + "Nedskrivningar av långfristiga fordringar hos gemensamt styrda företag": { + "account_number": "8174" + }, + "Nedskrivningar av andelar i övriga företag som det finns ett ägarintresse i": { + "account_number": "8176" + }, + "Nedskrivningar av långfristiga fordringar hos övriga företag": { + "account_number": "8177" + } + }, + "818 Återföringar av nedskrivningar av andelar i och långfristiga fordringar hos intresseföretag": { + "account_type": "Expense Account", + "is_group": 1, + "Återföringar av nedskrivningar av andelar i och långfristiga fordringar hos intresseföretag": { + "account_number": "8180" + }, + "Återföringar av nedskrivningar av andelar i intresseföretag": { + "account_number": "8181" + }, + "Återföringar av nedskrivningar av långfristiga fordringar hos intresseföretag": { + "account_number": "8182" + }, + "Återföringar av nedskrivningar av andelar i gemensamt styrda företag": { + "account_number": "8183" + }, + "Återföringar av nedskrivningar av långfristiga fordringar hos gemensamt styrda företag": { + "account_number": "8184" + }, + "Återföringar av nedskrivningar av andelar i övriga företag": { + "account_number": "8186" + }, + "Återföringar av nedskrivningar av långfristiga fordringar hos övriga företag": { + "account_number": "8187" + } + } + }, + "82 Resultat från övriga värdepapper och långfristiga fordringar (anläggningstillgångar)": { + "is_group": 1, + "821 Utdelningar på andelar i andra företag": { + "is_group": 1, + "Utdelningar på andelar i andra företag": { + "account_number": "8210" + }, + "Utdelningar, övriga företag": { + "account_number": "8212" + }, + "Insatsemissioner, övriga företag": { + "account_number": "8216" + } + }, + "822 Resultat vid försäljning av värdepapper i och långfristiga fordringar hos andra företag": { + "is_group": 1, + "Resultat vid försäljning av värdepapper i och långfristiga fordringar hos andra företag": { + "account_number": "8220" + }, + "Resultat vid försäljning av andelar i andra företag": { + "account_number": "8221" + }, + "Resultat vid försäljning av långfristiga fordringar hos andra företag": { + "account_number": "8222" + }, + "Resultat vid försäljning av derivat (långfristiga värdepappersinnehav)": { + "account_number": "8223" + } + }, + "823 Valutakursdifferenser på långfristiga fordringar": { + "is_group": 1, + "Valutakursdifferenser på långfristiga fordringar": { + "account_number": "8230" + }, + "Valutakursvinster på långfristiga fordringar": { + "account_number": "8231" + }, + "Valutakursförluster på långfristiga fordringar": { + "account_number": "8236" + } + }, + "824 Resultatandelar från handelsbolag (andra företag)": { + "is_group": 1, + "Resultatandelar från handelsbolag (andra företag)": { + "account_number": "8240" + } + }, + "825 Ränteintäkter från långfristiga fordringar hos och värdepapper i andra företag": { + "is_group": 1, + "Ränteintäkter från långfristiga fordringar hos och värdepapper i andra företag": { + "account_number": "8250" + }, + "Ränteintäkter från långfristiga fordringar": { + "account_number": "8251" + }, + "Ränteintäkter från övriga värdepapper": { + "account_number": "8252" + }, + "Skattefria ränteintäkter, långfristiga tillgångar": { + "account_number": "8254" + }, + "Avkastningsskatt kapitalplacering": { + "account_number": "8255" + } + }, + "826 Ränteintäkter från långfristiga fordringar hos koncernföretag": { + "is_group": 1, + "Ränteintäkter från långfristiga fordringar hos koncernföretag": { + "account_number": "8260" + }, + "Ränteintäkter från långfristiga fordringar hos moderföretag": { + "account_number": "8261" + }, + "Ränteintäkter från långfristiga fordringar hos dotterföretag": { + "account_number": "8262" + }, + "Ränteintäkter från långfristiga fordringar hos andra koncernföretag": { + "account_number": "8263" + } + }, + "827 Nedskrivningar av innehav av andelar i och långfristiga fordringar hos andra företag": { + "is_group": 1, + "Nedskrivningar av innehav av andelar i och långfristiga fordringar hos andra företag": { + "account_number": "8270" + }, + "Nedskrivningar av andelar i andra företag": { + "account_number": "8271" + }, + "Nedskrivningar av långfristiga fordringar hos andra företag": { + "account_number": "8272" + }, + "Nedskrivningar av övriga värdepapper hos andra företag": { + "account_number": "8273" + } + }, + "828 Återföringar av nedskrivningar av andelar i och långfristiga fordringar hos andra företag": { + "is_group": 1, + "Återföringar av nedskrivningar av andelar i och långfristiga fordringar hos andra företag": { + "account_number": "8280" + }, + "Återföringar av nedskrivningar av andelar i andra företag": { + "account_number": "8281" + }, + "Återföringar av nedskrivningar av långfristiga fordringar hos andra företag": { + "account_number": "8282" + }, + "Återföringar av nedskrivningar av övriga värdepapper i andra företag": { + "account_number": "8283" + } + }, + "829 Värdering till verkligt värde, anläggningstillgångar": { + "is_group": 1, + "Värdering till verkligt värde, anläggningstillgångar": { + "account_number": "8290" + }, + "Orealiserade värdeförändringar på anläggningstillgångar": { + "account_number": "8291" + }, + "Orealiserade värdeförändringar på derivatinstrument": { + "account_number": "8295" + } + } + }, + "83 Övriga ränteintäkter och liknande resultatposter": { + "is_group": 1, + "831 Ränteintäkter från omsättningstillgångar": { + "is_group": 1, + "Ränteintäkter från omsättningstillgångar": { + "account_number": "8310" + }, + "Ränteintäkter från bank": { + "account_number": "8311" + }, + "Ränteintäkter från kortfristiga placeringar": { + "account_number": "8312" + }, + "Ränteintäkter från kortfristiga fordringar": { + "account_number": "8313" + }, + "Skattefria ränteintäkter": { + "account_number": "8314", + "account_type": "Income Account" + }, + "Ränteintäkter för dold räntekompensation": { + "account_number": "8317" + }, + "Övriga ränteintäkter från omsättningstillgångar": { + "account_number": "8319" + } + }, + "832 Värdering till verkligt värde, omsättningstillgångar": { + "is_group": 1, + "Värdering till verkligt värde, omsättningstillgångar": { + "account_number": "8320" + }, + "Orealiserade värdeförändringar på omsättningstillgångar": { + "account_number": "8321" + }, + "Orealiserade värdeförändringar på derivatinstrument (oms.-tillg.)": { + "account_number": "8325" + } + }, + "833 Valutakursdifferenser på kortfristiga fordringar och placeringar": { + "is_group": 1, + "Valutakursdifferenser på kortfristiga fordringar och placeringar": { + "account_number": "8330" + }, + "Valutakursvinster på kortfristiga fordringar och placeringar": { + "account_number": "8331" + }, + "Valutakursförluster på kortfristiga fordringar och placeringar": { + "account_number": "8336" + } + }, + "834 Utdelningar på kortfristiga placeringar": { + "is_group": 1, + "Utdelningar på kortfristiga placeringar": { + "account_number": "8340" + } + }, + "835 Resultat vid försäljning av kortfristiga placeringar": { + "is_group": 1, + "Resultat vid försäljning av kortfristiga placeringar": { + "account_number": "8350" + } + }, + "836 Övriga ränteintäkter från koncernföretag": { + "is_group": 1, + "Övriga ränteintäkter från koncernföretag": { + "account_number": "8360" + }, + "Övriga ränteintäkter från moderföretag": { + "account_number": "8361" + }, + "Övriga ränteintäkter från dotterföretag": { + "account_number": "8362" + }, + "Övriga ränteintäkter från andra koncernföretag": { + "account_number": "8363" + } + }, + "837 Nedskrivningar av kortfristiga placeringar": { + "is_group": 1, + "Nedskrivningar av kortfristiga placeringar": { + "account_number": "8370" + } + }, + "838 Återföringar av nedskrivningar av kortfristiga placeringar": { + "is_group": 1, + "Återföringar av nedskrivningar av kortfristiga placeringar": { + "account_number": "8380" + } + }, + "839 Övriga finansiella intäkter": { + "is_group": 1, + "Övriga finansiella intäkter": { + "account_number": "8390" + } + } + }, + "84 Räntekostnader och liknande resultatposter": { + "is_group": 1, + "840 Räntekostnader (gruppkonto)": { + "is_group": 1, + "Räntekostnader (gruppkonto)": { + "account_number": "8400" + } + }, + "841 Räntekostnader för långfristiga skulder": { + "is_group": 1, + "Räntekostnader för långfristiga skulder": { + "account_number": "8410", + "account_type": "Expense Account" + }, + "Räntekostnader för obligations-, förlags- och konvertibla lån": { + "account_number": "8411" + }, + "Räntedel i årets pensionskostnad": { + "account_number": "8412" + }, + "Räntekostnader för checkräkningskredit": { + "account_number": "8413" + }, + "Räntekostnader för andra skulder till kreditinstitut": { + "account_number": "8415" + }, + "Räntekostnader för dold räntekompensation m.m.": { + "account_number": "8417" + }, + "Avdragspost för räntesubventioner": { + "account_number": "8418" + }, + "Övriga räntekostnader för långfristiga skulder": { + "account_number": "8419" + } + }, + "842 Räntekostnader för kortfristiga skulder": { + "is_group": 1, + "Räntekostnader för kortfristiga skulder": { + "account_number": "8420", + "account_type": "Expense Account" + }, + "Räntekostnader till kreditinstitut": { + "account_number": "8421", + "account_type": "Expense Account" + }, + "Dröjsmålsräntor för leverantörsskulder": { + "account_number": "8422", + "account_type": "Expense Account" + }, + "Räntekostnader för skatter och avgifter": { + "account_number": "8423", + "account_type": "Expense Account" + }, + "Räntekostnader byggnadskreditiv": { + "account_number": "8424" + }, + "Övriga räntekostnader för kortfristiga skulder": { + "account_number": "8429" + } + }, + "843 Valutakursdifferenser på skulder": { + "is_group": 1, + "Valutakursdifferenser på skulder": { + "account_number": "8430", + "account_type": "Expense Account" + }, + "Valutakursvinster på skulder": { + "account_number": "8431" + }, + "Valutakursförluster på skulder": { + "account_number": "8436" + } + }, + "844 Erhållna räntebidrag": { + "is_group": 1, + "Erhållna räntebidrag": { + "account_number": "8440" + } + }, + "845 Orealiserade värdeförändringar på skulder": { + "is_group": 1, + "Orealiserade värdeförändringar på skulder": { + "account_number": "8450" + }, + "Orealiserade värdeförändringar på skulder övriga": { + "account_number": "8451" + }, + "Orealiserade värdeförändringar på säkringsinstrument": { + "account_number": "8455" + } + }, + "846 Räntekostnader till koncernföretag": { + "is_group": 1, + "Räntekostnader till koncernföretag": { + "account_number": "8460" + }, + "Räntekostnader till moderföretag": { + "account_number": "8461" + }, + "Räntekostnader till dotterföretag": { + "account_number": "8462" + }, + "Räntekostnader till andra koncernföretag": { + "account_number": "8463" + } + }, + "848 Aktiverade ränteutgifter": { + "is_group": 1, + "Aktiverade ränteutgifter": { + "account_number": "8480" + } + }, + "849 Övriga skuldrelaterade poster": { + "is_group": 1, + "Övriga skuldrelaterade poster": { + "account_number": "8490" + }, + "Erhållet ackord på skulder till kreditinstitut m.m.": { + "account_number": "8491" + } + } + }, + "85 (Fri kontogrupp)": { + "is_group": 1, + "(Fri kontogrupp)": { + "account_number": "8500" + } + }, + "86 (Fri kontogrupp)": { + "is_group": 1, + "(Fri kontogrupp)": { + "account_number": "8600" + } + }, + "87 (Fri kontogrupp)": { + "is_group": 1, + "(Fri kontogrupp)": { + "account_number": "8700" + } + }, + "88 Bokslutsdispositioner": { + "is_group": 1, + "881 Förändring av periodiseringsfond": { + "is_group": 1, + "Förändring av periodiseringsfond": { + "account_number": "8810" + }, + "Avsättning till periodiseringsfond": { + "account_number": "8811" + }, + "Återföring från periodiseringsfond": { + "account_number": "8819" + } + }, + "882 Mottagna koncernbidrag": { + "is_group": 1, + "Mottagna koncernbidrag": { + "account_number": "8820" + } + }, + "883 Lämnade koncernbidrag": { + "is_group": 1, + "Lämnade koncernbidrag": { + "account_number": "8830" + } + }, + "884 Lämnade gottgörelser": { + "is_group": 1, + "Lämnade gottgörelser": { + "account_number": "8840" + } + }, + "885 Förändring av överavskrivningar": { + "is_group": 1, + "Förändring av överavskrivningar": { + "account_number": "8850" + }, + "Förändring av överavskrivningar, immateriella anläggningstillgångar": { + "account_number": "8851" + }, + "Förändring av överavskrivningar, byggnader och markanläggningar": { + "account_number": "8852" + }, + "Förändring av överavskrivningar, maskiner och inventarier": { + "account_number": "8853" + } + }, + "886 Förändring av ersättningsfond": { + "is_group": 1, + "Förändring av ersättningsfond": { + "account_number": "8860" + }, + "Avsättning till ersättningsfond för inventarier": { + "account_number": "8861" + }, + "Avsättning till ersättningsfond för byggnader och markanläggningar": { + "account_number": "8862" + }, + "Avsättning till ersättningsfond för djurlager i jordbruk och rensku00f6tsel": { + "account_number": "8864" + }, + "Ianspråktagande av ersättningsfond för avskrivningar": { + "account_number": "8865" + }, + "Ianspråktagande av ersättningsfond för annat än avskrivningar": { + "account_number": "8866" + }, + "Återföring från ersättningsfond": { + "account_number": "8869" + } + }, + "889 Övriga bokslutsdispositioner": { + "is_group": 1, + "Övriga bokslutsdispositioner": { + "account_number": "8890" + }, + "Nedskrivningar av konsolideringskaraktär av anläggningstillgångar": { + "account_number": "8892" + }, + "Förändring av lagerreserv": { + "account_number": "8896" + }, + "Övriga bokslutsdispositioner övriga": { + "account_number": "8899" + } + } + }, + "89 Skatter och årets resultat": { + "is_group": 1, + "891 Skatt som belastar årets resultat": { + "is_group": 1, + "Skatt som belastar årets resultat": { + "account_number": "8910" + } + }, + "892 Skatt på grund av ändrad beskattning": { + "is_group": 1, + "Skatt på grund av ändrad beskattning": { + "account_number": "8920" + } + }, + "893 Restituerad skatt": { + "is_group": 1, + "Restituerad skatt": { + "account_number": "8930" + } + }, + "894 Uppskjuten skatt": { + "is_group": 1, + "Uppskjuten skatt": { + "account_number": "8940" + } + }, + "898 Övriga skatter": { + "is_group": 1, + "Övriga skatter": { + "account_number": "8980" + } + }, + "899 Resultat": { + "is_group": 1, + "Resultat": { + "account_number": "8990" + }, + "Årets resultat": { + "account_number": "8999" + } + } + } + }, + "9 Eget Kapital": { + "root_type": "Equity", + "is_group": 1, + "90 Eget Kapital": { + "account_type": "Equity", + "is_group": 1, + "901 Eget kapital, delägare 1": { + "is_group": 1, + "Eget kapital": { + "account_number": "9010", + "account_type": "Equity" + }, + "Egna varuuttag": { + "account_number": "9011", + "account_type": "Equity" + }, + "Övriga egna uttag": { + "account_number": "9013", + "account_type": "Equity" + }, + "Årets kapitaltillskott": { + "account_number": "9017", + "account_type": "Equity" + }, + "Övriga egna insättningar": { + "account_number": "9018", + "account_type": "Equity" + }, + "Årets resultat": { + "account_number": "9019", + "account_type": "Equity" + } + }, + "902 Eget kapital, delägare 2": { + "is_group": 1, + "Eget kapital": { + "account_number": "9020", + "account_type": "Equity" + }, + "Egna varuuttag": { + "account_number": "9021", + "account_type": "Equity" + }, + "Övriga egna uttag": { + "account_number": "9023", + "account_type": "Equity" + }, + "Årets kapitaltillskott": { + "account_number": "9027", + "account_type": "Equity" + }, + "Övriga egna insättningar": { + "account_number": "9028", + "account_type": "Equity" + }, + "Årets resultat": { + "account_number": "9029", + "account_type": "Equity" + } + }, + "903 Eget kapital, delägare 3": { + "is_group": 1, + "Eget kapital": { + "account_number": "9030", + "account_type": "Equity" + }, + "Egna varuuttag": { + "account_number": "9031", + "account_type": "Equity" + }, + "Övriga egna uttag": { + "account_number": "9033", + "account_type": "Equity" + }, + "Årets kapitaltillskott": { + "account_number": "9037", + "account_type": "Equity" + }, + "Övriga egna insättningar": { + "account_number": "9038", + "account_type": "Equity" + }, + "Årets resultat": { + "account_number": "9039", + "account_type": "Equity" + } + }, + "904 Eget kapital, delägare 4": { + "is_group": 1, + "Eget kapital": { + "account_number": "9040", + "account_type": "Equity" + }, + "Egna varuuttag": { + "account_number": "9041", + "account_type": "Equity" + }, + "Övriga egna uttag": { + "account_number": "9043", + "account_type": "Equity" + }, + "Årets kapitaltillskott": { + "account_number": "9047", + "account_type": "Equity" + }, + "Övriga egna insättningar": { + "account_number": "9048", + "account_type": "Equity" + }, + "Årets resultat": { + "account_number": "9049", + "account_type": "Equity" + } + }, + "905 Avsättning till expansionsfond": { + "is_group": 1, + "Avsättning till expansionsfond": { + "account_number": "9050" + } + }, + "906 Eget kapital i ideella föreningar, stiftelser och registrerade trossamfund": { + "is_group": 1, + "Eget kapital i ideella föreningar, stiftelser och registrerade trossamfund": { + "account_number": "9060", + "account_type": "Equity" + }, + "Eget kapital/stiftelsekapital/grundkapital": { + "account_number": "9061" + }, + "Förändring i fond för verkligt värde": { + "account_number": "9065" + }, + "Värdesäkringsfond": { + "account_number": "9066" + }, + "Balanserad vinst eller förlust/balanserat kapital": { + "account_number": "9067" + }, + "Vinst eller förlust från föregående år": { + "account_number": "9068" + }, + "Årets resultat": { + "account_number": "9069" + } + }, + "907 Ändamålsbestämda medel": { + "is_group": 1, + "Ändamålsbestämda medel": { + "account_number": "9070", + "account_type": "Equity" + }, + "Ändamål 1": { + "account_number": "9071" + }, + "Ändamål 2": { + "account_number": "9072" + } + }, + "908 Bundet eget kapital": { + "is_group": 1, + "Bundet eget kapital": { + "account_number": "9080" + }, + "Aktiekapital": { + "account_number": "9081", + "account_type": "Equity" + }, + "Ej registrerat aktiekapital": { + "account_number": "9082" + }, + "Medlemsinsatser": { + "account_number": "9083", + "account_type": "Equity" + }, + "Förlagsinsatser": { + "account_number": "9084" + }, + "Uppskrivningsfond": { + "account_number": "9085" + }, + "Reservfond": { + "account_number": "9086", + "account_type": "Equity" + }, + "Bunden överkursfond": { + "account_number": "9087" + }, + "Fond för yttre underhåll": { + "account_number": "9088" + }, + "Fond för utvecklingsutgifter": { + "account_number": "9089" + } + }, + "909 Fritt eget kapital": { + "is_group": 1, + "Fritt eget kapital": { + "account_number": "9090", + "account_type": "Equity" + }, + "Balanserad vinst eller förlust": { + "account_number": "9091", + "account_type": "Equity" + }, + "Mottagna/lämnade koncernbidrag": { + "account_number": "9092" + }, + "Erhållna aktieägartillskott": { + "account_number": "9093" + }, + "Egna aktier": { + "account_number": "9094" + }, + "Fusionsresultat": { + "account_number": "9095" + }, + "Fond för verkligt värde": { + "account_number": "9096" + }, + "Fri överkursfond": { + "account_number": "9097" + }, + "Vinst eller förlust från föregående år": { + "account_number": "9098", + "account_type": "Equity" + }, + "Årets resultat": { + "account_number": "9099", + "account_type": "Equity" + } + } + }, + "91 Obeskattade reserver": { + "root_type": "Equity", + "is_group": 1, + "911 Periodiseringsfonder": { + "account_type": "Equity", + "is_group": 1, + "Periodiseringsfonder": { + "account_number": "9110" + } + }, + "912 Periodiseringsfond 2020": { + "is_group": 1, + "Periodiseringsfond 2020": { + "account_number": "9120", + "account_type": "Equity" + }, + "Periodiseringsfond 2021": { + "account_number": "9121", + "account_type": "Equity" + }, + "Periodiseringsfond 2022": { + "account_number": "9122", + "account_type": "Equity" + }, + "Periodiseringsfond 2023": { + "account_number": "9123", + "account_type": "Equity" + }, + "Periodiseringsfond 2024": { + "account_number": "9124", + "account_type": "Equity" + }, + "Periodiseringsfond 2016": { + "account_number": "9126", + "account_type": "Equity" + }, + "Periodiseringsfond 2017": { + "account_number": "9127", + "account_type": "Equity" + }, + "Periodiseringsfond 2018": { + "account_number": "9128", + "account_type": "Equity" + }, + "Periodiseringsfond 2019": { + "account_number": "9129", + "account_type": "Equity" + } + }, + "913 Periodiseringsfond 2020": { + "is_group": 1, + "Periodiseringsfond 2020": { + "account_number": "9130", + "account_type": "Equity" + }, + "Periodiseringsfond 2021": { + "account_number": "9131", + "account_type": "Equity" + }, + "Periodiseringsfond 2022": { + "account_number": "9132", + "account_type": "Equity" + }, + "Periodiseringsfond 2023": { + "account_number": "9133", + "account_type": "Equity" + }, + "Periodiseringsfond 2024": { + "account_number": "9134", + "account_type": "Equity" + }, + "Periodiseringsfond 2016": { + "account_number": "9136", + "account_type": "Equity" + }, + "Periodiseringsfond 2017": { + "account_number": "9137", + "account_type": "Equity" + }, + "Periodiseringsfond 2018": { + "account_number": "9138", + "account_type": "Equity" + }, + "Periodiseringsfond 2019": { + "account_number": "9139", + "account_type": "Equity" + } + }, + "915 Ackumulerade överavskrivningar": { + "is_group": 1, + "Ackumulerade överavskrivningar": { + "account_number": "9150", + "account_type": "Equity" + }, + "Ackumulerade överavskrivningar på immateriella anläggningstillgångar": { + "account_number": "9151" + }, + "Ackumulerade överavskrivningar på byggnader och markanläggningar": { + "account_number": "9152" + }, + "Ackumulerade överavskrivningar på maskiner och inventarier": { + "account_number": "9153" + } + }, + "916 Ersättningsfond": { + "is_group": 1, + "Ersättningsfond": { + "account_number": "9160" + }, + "Ersättningsfond maskiner och inventarier": { + "account_number": "9161" + }, + "Ersättningsfond byggnader och markanläggningar": { + "account_number": "9162" + }, + "Ersättningsfond för djurlager i jordbruk och renskötsel": { + "account_number": "9164" + } + }, + "919 Övriga obeskattade reserver": { + "is_group": 1, + "Övriga obeskattade reserver": { + "account_number": "9190" + }, + "Lagerreserv": { + "account_number": "9196" + }, + "Övriga obeskattade reserver övriga": { + "account_number": "9199" + } + } + }, + "92 Avsättningar": { + "account_type": "Equity", + "is_group": 1, + "921 Avsättningar för pensioner enligt tryggandelagen": { + "account_type": "Equity", + "is_group": 1, + "Avsättningar för pensioner enligt tryggandelagen": { + "account_number": "9210", + "account_type": "Equity" + } + }, + "922 Avsättningar för garantier": { + "account_type": "Equity", + "is_group": 1, + "Avsättningar för garantier": { + "account_number": "9220", + "account_type": "Equity" + } + }, + "923 Övriga avsättningar för pensioner och liknande förpliktelser": { + "account_type": "Equity", + "is_group": 1, + "Övriga avsättningar för pensioner och liknande förpliktelser": { + "account_number": "9230" + } + }, + "924 Avsättningar för uppskjutna skatter": { + "is_group": 1, + "Avsättningar för uppskjutna skatter": { + "account_number": "9240" + } + }, + "925 Övriga avsättningar för skatter": { + "is_group": 1, + "Övriga avsättningar för skatter": { + "account_number": "9250" + }, + "Avsättningar för tvistiga skatter": { + "account_number": "9252" + }, + "Avsättningar särskild löneskatt, deklarationspost": { + "account_number": "9253" + } + }, + "929 Övriga avsättningar": { + "account_type": "Equity", + "is_group": 1, + "Övriga avsättningar": { + "account_number": "9290", + "account_type": "Equity" + } + } + } + } + + } +} From 8f811728d97293744bb35f6a3bdba889708127c5 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 20 Dec 2024 12:18:01 +0530 Subject: [PATCH 10/50] feat(subcontracting): Added provision to create multiple Subcontracting Orders against a single Purchase Order (backport #44711) (#44782) * feat(subcontracting): Added provision to create multiple Subcontracting Orders against a single Purchase Order (#44711) * feat(subcontracting): Added provision to create multiple Subcontracting Orders from a single Subcontracted Purchase Order * refactor(new_sc_flow_2): Fixed error thrown by semgrep (cherry picked from commit 3eba6bf3ddcf911638681a83522e4e47196183ae) # Conflicts: # erpnext/buying/doctype/purchase_order/purchase_order.js # erpnext/buying/doctype/purchase_order/test_purchase_order.py # erpnext/buying/doctype/purchase_order_item/purchase_order_item.json # erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json # erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.json * feat(subcontracting): Added provision to create multiple Subcontracting Orders against a single Purchase Order (#44711) * feat(subcontracting): Added provision to create multiple Subcontracting Orders from a single Subcontracted Purchase Order * refactor(new_sc_flow_2): Fixed error thrown by semgrep * fix: Resolved errors and removed code from develop branch merged by mistake --------- Co-authored-by: Mihir Kandoi --- .../doctype/purchase_order/purchase_order.js | 14 ++- .../doctype/purchase_order/purchase_order.py | 61 ++++----- .../purchase_order/test_purchase_order.py | 116 +++++++++++++++++- .../purchase_order_item.json | 13 +- .../purchase_order_item.py | 1 + .../controllers/subcontracting_controller.py | 19 +++ .../tests/test_subcontracting_controller.py | 3 +- .../subcontracting_order.js | 30 ++++- .../subcontracting_order.py | 50 ++++++-- .../test_subcontracting_order.py | 6 - .../subcontracting_order_item.json | 14 ++- .../subcontracting_order_item.py | 1 + .../subcontracting_order_service_item.json | 2 +- .../subcontracting_order_service_item.py | 2 + 14 files changed, 272 insertions(+), 60 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js index e71f24187940..4cc383912764 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order.js @@ -400,11 +400,15 @@ erpnext.buying.PurchaseOrderController = class PurchaseOrderController extends ( ); } } else { - cur_frm.add_custom_button( - __("Subcontracting Order"), - this.make_subcontracting_order, - __("Create") - ); + if (!doc.items.every((item) => item.qty == item.sco_qty)) { + this.frm.add_custom_button( + __("Subcontracting Order"), + () => { + me.make_subcontracting_order(); + }, + __("Create") + ); + } } } } diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 6ba9cb69f9fc..26c0101b49b6 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -867,27 +867,40 @@ def make_inter_company_sales_order(source_name, target_doc=None): @frappe.whitelist() def make_subcontracting_order(source_name, target_doc=None, save=False, submit=False, notify=False): - target_doc = get_mapped_subcontracting_order(source_name, target_doc) - - if (save or submit) and frappe.has_permission(target_doc.doctype, "create"): - target_doc.save() + if not is_po_fully_subcontracted(source_name): + target_doc = get_mapped_subcontracting_order(source_name, target_doc) + + if (save or submit) and frappe.has_permission(target_doc.doctype, "create"): + target_doc.save() + + if submit and frappe.has_permission(target_doc.doctype, "submit", target_doc): + try: + target_doc.submit() + except Exception as e: + target_doc.add_comment("Comment", _("Submit Action Failed") + "

" + str(e)) + + if notify: + frappe.msgprint( + _("Subcontracting Order {0} created.").format( + get_link_to_form(target_doc.doctype, target_doc.name) + ), + indicator="green", + alert=True, + ) - if submit and frappe.has_permission(target_doc.doctype, "submit", target_doc): - try: - target_doc.submit() - except Exception as e: - target_doc.add_comment("Comment", _("Submit Action Failed") + "

" + str(e)) + return target_doc + else: + frappe.throw(_("This PO has been fully subcontracted.")) - if notify: - frappe.msgprint( - _("Subcontracting Order {0} created.").format( - get_link_to_form(target_doc.doctype, target_doc.name) - ), - indicator="green", - alert=True, - ) - return target_doc +def is_po_fully_subcontracted(po_name): + table = frappe.qb.DocType("Purchase Order Item") + query = ( + frappe.qb.from_(table) + .select(table.name) + .where((table.parent == po_name) & (table.qty != table.sco_qty)) + ) + return not query.run(as_dict=True) def get_mapped_subcontracting_order(source_name, target_doc=None): @@ -931,7 +944,8 @@ def post_process(source_doc, target_doc): "material_request": "material_request", "material_request_item": "material_request_item", }, - "field_no_map": [], + "field_no_map": ["qty", "fg_item_qty", "amount"], + "condition": lambda item: item.qty != item.sco_qty, }, }, target_doc, @@ -939,12 +953,3 @@ def post_process(source_doc, target_doc): ) return target_doc - - -@frappe.whitelist() -def is_subcontracting_order_created(po_name) -> bool: - return ( - True - if frappe.db.exists("Subcontracting Order", {"purchase_order": po_name, "docstatus": ["=", 1]}) - else False - ) diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py index dbfcbf60b266..5d8ce73e8ab6 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py @@ -1004,7 +1004,7 @@ def test_update_items_for_subcontracting_purchase_order(self): ) def update_items(po, qty): - trans_items = [po.items[0].as_dict()] + trans_items = [po.items[0].as_dict().update({"docname": po.items[0].name})] trans_items[0]["qty"] = qty trans_items[0]["fg_item_qty"] = qty trans_items = json.dumps(trans_items, default=str) @@ -1059,6 +1059,73 @@ def update_items(po, qty): self.assertEqual(po.items[0].qty, 30) self.assertEqual(po.items[0].fg_item_qty, 30) + def test_new_sc_flow(self): + from erpnext.buying.doctype.purchase_order.purchase_order import make_subcontracting_order + + po = create_po_for_sc_testing() + sco = make_subcontracting_order(po.name) + + sco.items[0].qty = 5 + sco.items.pop(1) + sco.items[1].qty = 25 + sco.save() + sco.submit() + + # Test - 1: Quantity of Service Items should change based on change in Quantity of its corresponding Finished Goods Item + self.assertEqual(sco.service_items[0].qty, 5) + + # Test - 2: Subcontracted Quantity for the PO Items of each line item should be updated accordingly + po.reload() + self.assertEqual(po.items[0].sco_qty, 5) + self.assertEqual(po.items[1].sco_qty, 0) + self.assertEqual(po.items[2].sco_qty, 12.5) + + # Test - 3: Amount for both FG Item and its Service Item should be updated correctly based on change in Quantity + self.assertEqual(sco.items[0].amount, 2000) + self.assertEqual(sco.service_items[0].amount, 500) + + # Test - 4: Service Items should be removed if its corresponding Finished Good line item is deleted + self.assertEqual(len(sco.service_items), 2) + + # Test - 5: Service Item quantity calculation should be based upon conversion factor calculated from its corresponding PO Item + self.assertEqual(sco.service_items[1].qty, 12.5) + + sco = make_subcontracting_order(po.name) + + sco.items[0].qty = 6 + + # Test - 6: Saving document should not be allowed if Quantity exceeds available Subcontracting Quantity of any Purchase Order Item + self.assertRaises(frappe.ValidationError, sco.save) + + sco.items[0].qty = 5 + sco.items.pop() + sco.items.pop() + sco.save() + sco.submit() + + sco = make_subcontracting_order(po.name) + + # Test - 7: Since line item 1 is now fully subcontracted, new SCO should by default only have the remaining 2 line items + self.assertEqual(len(sco.items), 2) + + sco.items.pop(0) + sco.save() + sco.submit() + + # Test - 8: Subcontracted Quantity for each PO Item should be subtracted if SCO gets cancelled + po.reload() + self.assertEqual(po.items[2].sco_qty, 25) + sco.cancel() + po.reload() + self.assertEqual(po.items[2].sco_qty, 12.5) + + sco = make_subcontracting_order(po.name) + sco.save() + sco.submit() + + # Test - 8: Since this PO is now fully subcontracted, creating a new SCO from it should throw error + self.assertRaises(frappe.ValidationError, make_subcontracting_order, po.name) + @change_settings("Buying Settings", {"auto_create_subcontracting_order": 1}) def test_auto_create_subcontracting_order(self): from erpnext.controllers.tests.test_subcontracting_controller import ( @@ -1124,6 +1191,53 @@ def test_po_billed_amount_against_return_entry(self): self.assertEqual(po.per_billed, 100) +def create_po_for_sc_testing(): + from erpnext.controllers.tests.test_subcontracting_controller import ( + make_bom_for_subcontracted_items, + make_raw_materials, + make_service_items, + make_subcontracted_items, + ) + + make_subcontracted_items() + make_raw_materials() + make_service_items() + make_bom_for_subcontracted_items() + + service_items = [ + { + "warehouse": "_Test Warehouse - _TC", + "item_code": "Subcontracted Service Item 1", + "qty": 10, + "rate": 100, + "fg_item": "Subcontracted Item SA1", + "fg_item_qty": 10, + }, + { + "warehouse": "_Test Warehouse - _TC", + "item_code": "Subcontracted Service Item 2", + "qty": 20, + "rate": 25, + "fg_item": "Subcontracted Item SA2", + "fg_item_qty": 15, + }, + { + "warehouse": "_Test Warehouse - _TC", + "item_code": "Subcontracted Service Item 3", + "qty": 25, + "rate": 10, + "fg_item": "Subcontracted Item SA3", + "fg_item_qty": 50, + }, + ] + + return create_purchase_order( + rm_items=service_items, + is_subcontracted=1, + supplier_warehouse="_Test Warehouse 1 - _TC", + ) + + def prepare_data_for_internal_transfer(): from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier from erpnext.selling.doctype.customer.test_customer import create_internal_customer diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json index e3e8def7ffdf..4fc20594ffab 100644 --- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json +++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json @@ -1,7 +1,7 @@ { "actions": [], "autoname": "hash", - "creation": "2013-05-24 19:29:06", + "creation": "2024-12-09 12:54:24.652161", "doctype": "DocType", "document_type": "Document", "editable_grid": 1, @@ -26,6 +26,7 @@ "quantity_and_rate", "qty", "stock_uom", + "sco_qty", "col_break2", "uom", "conversion_factor", @@ -909,13 +910,21 @@ { "fieldname": "column_break_fyqr", "fieldtype": "Column Break" + }, + { + "allow_on_submit": 1, + "fieldname": "sco_qty", + "fieldtype": "Float", + "label": "Subcontracted Quantity", + "no_copy": 1, + "read_only": 1 } ], "idx": 1, "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2024-02-05 11:23:24.859435", + "modified": "2024-12-10 12:11:18.536089", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order Item", diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.py b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.py index e9cc2b4eecfe..b80abda56c3a 100644 --- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.py +++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.py @@ -80,6 +80,7 @@ class PurchaseOrderItem(Document): sales_order_item: DF.Data | None sales_order_packed_item: DF.Data | None schedule_date: DF.Date + sco_qty: DF.Float stock_qty: DF.Float stock_uom: DF.Link stock_uom_rate: DF.Currency diff --git a/erpnext/controllers/subcontracting_controller.py b/erpnext/controllers/subcontracting_controller.py index 5fb1ee468cda..75cb5516348e 100644 --- a/erpnext/controllers/subcontracting_controller.py +++ b/erpnext/controllers/subcontracting_controller.py @@ -103,6 +103,19 @@ def validate_items(self): _("Row {0}: Item {1} must be a subcontracted item.").format(item.idx, item.item_name) ) + if ( + self.doctype not in "Subcontracting Receipt" + and item.qty + > flt(get_pending_sco_qty(self.purchase_order).get(item.purchase_order_item)) + / item.sc_conversion_factor + ): + frappe.throw( + _( + "Row {0}: Item {1}'s quantity cannot be higher than the available quantity." + ).format(item.idx, item.item_name) + ) + item.amount = item.qty * item.rate + if item.bom: is_active, bom_item = frappe.get_value("BOM", item.bom, ["is_active", "item"]) @@ -1110,6 +1123,12 @@ def get_item_details(items): return item_details +def get_pending_sco_qty(po_name): + table = frappe.qb.DocType("Purchase Order Item") + query = frappe.qb.from_(table).select(table.name, table.qty, table.sco_qty).where(table.parent == po_name) + return {item.name: item.qty - item.sco_qty for item in query.run(as_dict=True)} + + @frappe.whitelist() def make_rm_stock_entry( subcontract_order, rm_items=None, order_doctype="Subcontracting Order", target_doc=None diff --git a/erpnext/controllers/tests/test_subcontracting_controller.py b/erpnext/controllers/tests/test_subcontracting_controller.py index 84326bafef2e..0bc348e88761 100644 --- a/erpnext/controllers/tests/test_subcontracting_controller.py +++ b/erpnext/controllers/tests/test_subcontracting_controller.py @@ -1261,6 +1261,7 @@ def make_raw_materials(): for item, properties in raw_materials.items(): if not frappe.db.exists("Item", item): properties.update({"is_stock_item": 1}) + properties.update({"valuation_rate": 100}) make_item(item, properties) @@ -1311,7 +1312,7 @@ def make_bom_for_subcontracted_items(): for item_code, raw_materials in boms.items(): if not frappe.db.exists("BOM", {"item": item_code}): - make_bom(item=item_code, raw_materials=raw_materials, rate=100) + make_bom(item=item_code, raw_materials=raw_materials, rate=100, currency="INR") def set_backflush_based_on(based_on): diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js index c6ee3a3e0e35..e9513a47597d 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js @@ -5,10 +5,38 @@ frappe.provide("erpnext.buying"); erpnext.landed_cost_taxes_and_charges.setup_triggers("Subcontracting Order"); +// client script for Subcontracting Order Item is not necessarily required as the server side code will do everything that is necessary. +// this is just so that the user does not get potentially confused +frappe.ui.form.on("Subcontracting Order Item", { + qty(frm, cdt, cdn) { + const row = locals[cdt][cdn]; + frappe.model.set_value(cdt, cdn, "amount", row.qty * row.rate); + const service_item = frm.doc.service_items[row.idx - 1]; + frappe.model.set_value( + service_item.doctype, + service_item.name, + "qty", + row.qty * row.sc_conversion_factor + ); + frappe.model.set_value(service_item.doctype, service_item.name, "fg_item_qty", row.qty); + frappe.model.set_value( + service_item.doctype, + service_item.name, + "amount", + row.qty * row.sc_conversion_factor * service_item.rate + ); + }, + before_items_remove(frm, cdt, cdn) { + const row = locals[cdt][cdn]; + frm.toggle_enable(["service_items"], true); + frm.get_field("service_items").grid.grid_rows[row.idx - 1].remove(); + frm.toggle_enable(["service_items"], false); + }, +}); + frappe.ui.form.on("Subcontracting Order", { setup: (frm) => { frm.get_field("items").grid.cannot_add_rows = true; - frm.get_field("items").grid.only_sortable(); frm.trigger("set_queries"); frm.set_indicator_formatter("item_code", (doc) => (doc.qty <= doc.received_qty ? "green" : "orange")); diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py index 8419c8e90935..f6d3fa041484 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py @@ -6,7 +6,6 @@ from frappe.model.mapper import get_mapped_doc from frappe.utils import flt -from erpnext.buying.doctype.purchase_order.purchase_order import is_subcontracting_order_created from erpnext.buying.utils import check_on_hold_or_closed_status from erpnext.controllers.subcontracting_controller import SubcontractingController from erpnext.stock.stock_balance import update_bin_qty @@ -120,20 +119,15 @@ def validate(self): def on_submit(self): self.update_prevdoc_status() self.update_status() + self.update_sco_qty_in_po() def on_cancel(self): self.update_prevdoc_status() self.update_status() + self.update_sco_qty_in_po(cancel=True) def validate_purchase_order_for_subcontracting(self): if self.purchase_order: - if is_subcontracting_order_created(self.purchase_order): - frappe.throw( - _( - "Only one Subcontracting Order can be created against a Purchase Order, cancel the existing Subcontracting Order to create a new one." - ) - ) - po = frappe.get_doc("Purchase Order", self.purchase_order) if not po.is_subcontracted: @@ -154,10 +148,23 @@ def validate_purchase_order_for_subcontracting(self): frappe.throw(_("Please select a Subcontracting Purchase Order.")) def validate_service_items(self): - for item in self.service_items: - if frappe.get_value("Item", item.item_code, "is_stock_item"): - msg = f"Service Item {item.item_name} must be a non-stock item." - frappe.throw(_(msg)) + purchase_order_items = [item.purchase_order_item for item in self.items] + self.service_items = [ + service_item + for service_item in self.service_items + if service_item.purchase_order_item in purchase_order_items + ] + + for service_item in self.service_items: + if frappe.get_value("Item", service_item.item_code, "is_stock_item"): + frappe.throw(_("Service Item {0} must be a non-stock item.").format(service_item.item_code)) + + item = next( + item for item in self.items if item.purchase_order_item == service_item.purchase_order_item + ) + service_item.qty = item.qty * item.sc_conversion_factor + service_item.fg_item_qty = item.qty + service_item.amount = service_item.qty * service_item.rate def validate_supplied_items(self): if self.supplier_warehouse: @@ -241,6 +248,18 @@ def populate_items_table(self): for si in self.service_items: if si.fg_item: item = frappe.get_doc("Item", si.fg_item) + + po_item = frappe.get_doc("Purchase Order Item", si.purchase_order_item) + available_qty = po_item.qty - po_item.sco_qty + + if available_qty == 0: + continue + + si.qty = available_qty + conversion_factor = po_item.qty / po_item.fg_item_qty + si.fg_item_qty = available_qty / conversion_factor + si.amount = available_qty * si.rate + bom = ( frappe.db.get_value( "Subcontracting BOM", @@ -257,6 +276,7 @@ def populate_items_table(self): "schedule_date": self.schedule_date, "description": item.description, "qty": si.fg_item_qty, + "sc_conversion_factor": conversion_factor, "stock_uom": item.stock_uom, "bom": bom, "purchase_order_item": si.purchase_order_item, @@ -310,6 +330,12 @@ def update_status(self, status=None, update_modified=True): self.update_ordered_qty_for_subcontracting() self.update_reserved_qty_for_subcontracting() + def update_sco_qty_in_po(self, cancel=False): + for service_item in self.service_items: + doc = frappe.get_doc("Purchase Order Item", service_item.purchase_order_item) + doc.sco_qty = (doc.sco_qty + service_item.qty) if not cancel else (doc.sco_qty - service_item.qty) + doc.save() + @frappe.whitelist() def make_subcontracting_receipt(source_name, target_doc=None): diff --git a/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py index ac87239e73ed..43592b628ad1 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py @@ -40,12 +40,6 @@ def setUp(self): make_service_items() make_bom_for_subcontracted_items() - def test_populate_items_table(self): - sco = get_subcontracting_order() - sco.items = None - sco.populate_items_table() - self.assertEqual(len(sco.service_items), len(sco.items)) - def test_set_missing_values(self): sco = get_subcontracting_order() before = {sco.total_qty, sco.total, sco.total_additional_costs} diff --git a/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json b/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json index 502a28b3ec62..31616944fdac 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json +++ b/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json @@ -51,7 +51,8 @@ "project", "section_break_34", "purchase_order_item", - "page_break" + "page_break", + "sc_conversion_factor" ], "fields": [ { @@ -144,8 +145,8 @@ "fieldtype": "Float", "in_list_view": 1, "label": "Quantity", + "non_negative": 1, "print_width": "60px", - "read_only": 1, "reqd": 1, "width": "60px" }, @@ -381,13 +382,20 @@ "no_copy": 1, "read_only": 1, "search_index": 1 + }, + { + "fieldname": "sc_conversion_factor", + "fieldtype": "Float", + "hidden": 1, + "label": "SC Conversion Factor", + "read_only": 1 } ], "idx": 1, "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2024-12-06 15:23:05.252346", + "modified": "2024-12-13 13:35:28.935898", "modified_by": "Administrator", "module": "Subcontracting", "name": "Subcontracting Order Item", diff --git a/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.py b/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.py index 7a426f91cb00..d8f2e5664e73 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.py +++ b/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.py @@ -42,6 +42,7 @@ class SubcontractingOrderItem(Document): received_qty: DF.Float returned_qty: DF.Float rm_cost_per_qty: DF.Currency + sc_conversion_factor: DF.Float schedule_date: DF.Date | None service_cost_per_qty: DF.Currency stock_uom: DF.Link diff --git a/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.json b/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.json index f1e94e125a98..ad3dfe34c888 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.json +++ b/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.json @@ -155,7 +155,7 @@ ], "istable": 1, "links": [], - "modified": "2023-11-30 13:29:31.017440", + "modified": "2024-12-05 17:33:46.099601", "modified_by": "Administrator", "module": "Subcontracting", "name": "Subcontracting Order Service Item", diff --git a/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.py b/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.py index cc4901baf45c..661a2b2702ce 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.py +++ b/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.py @@ -19,6 +19,8 @@ class SubcontractingOrderServiceItem(Document): fg_item_qty: DF.Float item_code: DF.Link item_name: DF.Data + material_request: DF.Link | None + material_request_item: DF.Data | None parent: DF.Data parentfield: DF.Data parenttype: DF.Data From cc1834b0ccb1c2f5ab1202d4d01aca58dfe56f01 Mon Sep 17 00:00:00 2001 From: mahsem <137205921+mahsem@users.noreply.github.com> Date: Sat, 14 Dec 2024 07:12:19 +0100 Subject: [PATCH 11/50] fix: Swedish tax templates (cherry picked from commit 73112fa3c9c21389f0b4e5938686bb5780df8254) --- .../setup_wizard/data/country_wise_tax.json | 197 +++++++++++++++++- 1 file changed, 194 insertions(+), 3 deletions(-) diff --git a/erpnext/setup/setup_wizard/data/country_wise_tax.json b/erpnext/setup/setup_wizard/data/country_wise_tax.json index efe1d705c51c..9f10785dac13 100644 --- a/erpnext/setup/setup_wizard/data/country_wise_tax.json +++ b/erpnext/setup/setup_wizard/data/country_wise_tax.json @@ -4500,9 +4500,200 @@ }, "Sweden": { - "Sweden Tax": { - "account_name": "VAT", - "tax_rate": 25.00 + "tax_categories": [], + "chart_of_accounts": { + "*": { + "sales_tax_templates": [ + { + "title": "Försäljning Moms 25%", + "is_default": 0, + "taxes": [ + { + "account_head": { + "account_name": "Utgående moms, 25 %", + "account_number": "2610", + "tax_rate": 25.00 + }, + "description": "Moms 25%", + "rate": 25.00 + } + ] + }, + { + "title": "Försäljning Moms 12%", + "is_default": 0, + "taxes": [ + { + "account_head": { + "account_name": "Utgående moms, 12 %", + "account_number": "2620", + "tax_rate": 12.00 + }, + "description": "Moms 12%", + "rate": 12.00 + } + ] + }, + { + "title": "Försäljning Moms 6%", + "is_default": 0, + "taxes": [ + { + "account_head": { + "account_name": "Utgående moms, 6 %", + "account_number": "2630", + "tax_rate": 6.00 + }, + "description": "Moms 6%", + "rate": 6.00 + } + ] + }, + { + "title": "Försäljning Moms 0%", + "is_default": 0, + "taxes": [ + { + "account_head": { + "account_name": "Utgående moms, 6 %", + "account_number": "2630", + "tax_rate": 0.00 + }, + "description": "Moms 0%", + "rate": 0.00 + } + ] + } + ], + "purchase_tax_templates": [ + { + "title": "Inköp Moms 25%", + "is_default": 0, + "taxes": [ + { + "account_head": { + "account_name": "Ingående moms", + "account_number": "2640", + "root_type": "Liability", + "tax_rate": 25.00 + }, + "description": "Moms 25%", + "rate": 25.00 + } + ] + }, + { + "title": "Inköp Moms 12%", + "is_default": 0, + "taxes": [ + { + "account_head": { + "account_name": "Ingående moms", + "account_number": "2640", + "root_type": "Liability", + "tax_rate": 12.00 + }, + "description": "Moms 12%", + "rate": 12.00 + } + ] + }, + { + "title": "Inköp Moms 6%", + "is_default": 0, + "taxes": [ + { + "account_head": { + "account_name": "Ingående moms", + "account_number": "2640", + "root_type": "Liability", + "tax_rate": 6.00 + }, + "description": "Moms 6%", + "rate": 6.00 + } + ] + }, + { + "title": "Inköp Moms 0%", + "is_default": 0, + "taxes": [ + { + "account_head": { + "account_name": "Ingående moms", + "account_number": "2640", + "root_type": "Liability", + "tax_rate": 0.00 + }, + "description": "Moms 0%", + "rate": 0.00 + } + ] + } + ], + "item_tax_templates": [ + { + "title": "Artikel Moms 25%", + "taxes": [ + { + "tax_type": { + "account_name": "Utgående moms, 25 %", + "account_number": "2610", + "root_type": "Liability", + "tax_rate": 25.00 + }, + "description": "Moms 25%", + "tax_rate": 25.00 + } + ] + }, + { + "title": "Artikel Moms 12%", + "taxes": [ + { + "tax_type": { + "account_name": "Utgående moms, 12 %", + "account_number": "2620", + "root_type": "Liability", + "tax_rate": 12.00 + }, + "description": "Moms 12%", + "tax_rate": 12.00 + } + ] + }, + { + "title": "Artikel Moms 6%", + "taxes": [ + { + "tax_type": { + "account_name": "Utgående moms, 6 %", + "account_number": "2630", + "root_type": "Liability", + "tax_rate": 6.00 + }, + "description": "Moms 6%", + "tax_rate": 6.00 + } + ] + }, + { + "title": "Artikel Moms 0%", + "taxes": [ + { + "tax_type": { + "account_name": "Utgående moms, 0 %", + "account_number": "2611", + "root_type": "Liability", + "tax_rate": 0.00 + }, + "description": "Moms 0%", + "tax_rate": 0.00 + } + ] + } + ] + } } }, From ad57e33cd7247c6b822469582e15939dd7a3e80b Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 20 Dec 2024 19:38:52 +0530 Subject: [PATCH 12/50] fix: slow posting datetime update (backport #44799) (#44805) fix: slow posting datetime update (#44799) (cherry picked from commit a7b5e2565bf93b5d08d754b3e6765fef97ab70b6) Co-authored-by: rohitwaghchaure --- .../test_serial_and_batch_bundle.py | 2 ++ .../doctype/stock_ledger_entry/stock_ledger_entry.py | 11 +++-------- .../stock_reconciliation/test_stock_reconciliation.py | 1 + erpnext/stock/stock_ledger.py | 1 - 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py index 5fe79384e6d5..647082baa687 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py @@ -186,6 +186,7 @@ def test_old_batch_valuation(self): } ) + doc.set_posting_datetime() doc.flags.ignore_permissions = True doc.flags.ignore_mandatory = True doc.flags.ignore_links = True @@ -586,6 +587,7 @@ def test_serial_no_valuation_for_legacy_ledgers(self): "company": "_Test Company", } ) + doc.set_posting_datetime() doc.flags.ignore_permissions = True doc.flags.ignore_mandatory = True doc.flags.ignore_links = True diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py index 5aeabeeec56c..6f5acd64d445 100644 --- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py +++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py @@ -88,6 +88,7 @@ def validate(self): self.flags.ignore_submit_comment = True from erpnext.stock.utils import validate_disabled_warehouse, validate_warehouse_company + self.set_posting_datetime() self.validate_mandatory() self.validate_batch() validate_disabled_warehouse(self.warehouse) @@ -98,15 +99,10 @@ def validate(self): self.validate_with_last_transaction_posting_time() self.validate_inventory_dimension_negative_stock() - def set_posting_datetime(self, save=False): + def set_posting_datetime(self): from erpnext.stock.utils import get_combine_datetime - if save: - posting_datetime = get_combine_datetime(self.posting_date, self.posting_time) - if not self.posting_datetime or self.posting_datetime != posting_datetime: - self.db_set("posting_datetime", posting_datetime) - else: - self.posting_datetime = get_combine_datetime(self.posting_date, self.posting_time) + self.posting_datetime = get_combine_datetime(self.posting_date, self.posting_time) def validate_inventory_dimension_negative_stock(self): if self.is_cancelled or self.actual_qty >= 0: @@ -173,7 +169,6 @@ def _get_inventory_dimensions(self): return inv_dimension_dict def on_submit(self): - self.set_posting_datetime(save=True) self.check_stock_frozen_date() # Added to handle few test cases where serial_and_batch_bundles are not required diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py index 9754443d4ac9..a3673063a48e 100644 --- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py @@ -1242,6 +1242,7 @@ def test_stock_reco_with_legacy_batch(self): } ) + doc.set_posting_datetime() doc.flags.ignore_permissions = True doc.flags.ignore_mandatory = True doc.flags.ignore_links = True diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index 1e1b24115696..d11c19446bbf 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -222,7 +222,6 @@ def make_entry(args, allow_negative_stock=False, via_landed_cost_voucher=False): sle.flags.ignore_permissions = 1 sle.allow_negative_stock = allow_negative_stock sle.via_landed_cost_voucher = via_landed_cost_voucher - sle.set_posting_datetime() sle.submit() # Added to handle the case when the stock ledger entry is created from the repostig From 16b013fab27a84c3889027db255166b76688efc4 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Sat, 21 Dec 2024 10:26:25 +0530 Subject: [PATCH 13/50] fix: Duplicate entry ' EF1DE8B2E1B6' for key 'PRIMARY' (backport #44809) (#44814) fix: Duplicate entry ' EF1DE8B2E1B6' for key 'PRIMARY' (#44809) (cherry picked from commit 56f561cdaa0689afbb14a8f6896e9a90dee91af9) Co-authored-by: rohitwaghchaure --- .../serial_and_batch_bundle.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index 6ff0317dce60..af378ca2f0b0 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -807,7 +807,7 @@ def validate_serial_batch_no(self, serial_batches): ) for serial_no, batch_no in serial_batches.items(): - if correct_batches.get(serial_no) != batch_no: + if correct_batches.get(serial_no) and correct_batches.get(serial_no) != batch_no: self.throw_error_message( f"Serial No {bold(serial_no)} does not belong to Batch No {bold(batch_no)}" ) @@ -1186,19 +1186,19 @@ def parse_csv_file_to_get_serial_batch(reader): continue if has_serial_no or (has_serial_no and has_batch_no): - _dict = {"serial_no": row[0], "qty": 1} + _dict = {"serial_no": row[0].strip(), "qty": 1} if has_batch_no: _dict.update( { - "batch_no": row[1], + "batch_no": row[1].strip(), "qty": row[2], } ) batch_nos.append( { - "batch_no": row[1], + "batch_no": row[1].strip(), "qty": row[2], } ) @@ -1207,7 +1207,7 @@ def parse_csv_file_to_get_serial_batch(reader): elif has_batch_no: batch_nos.append( { - "batch_no": row[0], + "batch_no": row[0].strip(), "qty": row[1], } ) @@ -1251,7 +1251,7 @@ def make_serial_nos(item_code, serial_nos): "Item", item_code, ["description", "item_code", "item_name", "warranty_period"], as_dict=1 ) - serial_nos = [d.get("serial_no") for d in serial_nos if d.get("serial_no")] + serial_nos = [d.get("serial_no").strip() for d in serial_nos if d.get("serial_no")] existing_serial_nos = frappe.get_all("Serial No", filters={"name": ("in", serial_nos)}) existing_serial_nos = [d.get("name") for d in existing_serial_nos if d.get("name")] From d137f780bd072f0baf18feef734157c90318674b Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 19 Dec 2024 17:06:54 +0530 Subject: [PATCH 14/50] fix: Ledger repost support for extending app doctypes (cherry picked from commit ed231abb54544f7362812500d9cbaefce09f778d) --- .../repost_accounting_ledger.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py b/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py index 0bd9a2a05154..7f2d437aece3 100644 --- a/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py +++ b/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py @@ -1,6 +1,8 @@ # Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt +import inspect + import frappe from frappe import _, qb from frappe.model.document import Document @@ -142,6 +144,8 @@ def on_submit(self): @frappe.whitelist() def start_repost(account_repost_doc=str) -> None: + from erpnext.accounts.general_ledger import make_reverse_gl_entries + frappe.flags.through_repost_accounting_ledger = True if account_repost_doc: repost_doc = frappe.get_doc("Repost Accounting Ledger", account_repost_doc) @@ -177,6 +181,14 @@ def start_repost(account_repost_doc=str) -> None: if not repost_doc.delete_cancelled_entries: doc.make_gl_entries(1) doc.make_gl_entries() + else: + if hasattr(doc, "make_gl_entries") and callable(doc.make_gl_entries): + if not repost_doc.delete_cancelled_entries: + if "cancel" in inspect.getfullargspec(doc.make_gl_entries): + doc.make_gl_entries(cancel=1) + else: + make_reverse_gl_entries(voucher_type=doc.doctype, voucher_no=doc.name) + doc.make_gl_entries() def get_allowed_types_from_settings(): From b5596d98e3e6f59d6ac0ee8d7266379ad25ca1b5 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 22 Dec 2024 20:34:31 +0530 Subject: [PATCH 15/50] fix: Add hooks for repost allowed doctypes (cherry picked from commit 919abd2c03865ab671c6977f735638b2f43753b0) --- .../repost_accounting_ledger/repost_accounting_ledger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py b/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py index 7f2d437aece3..73977f5d5605 100644 --- a/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py +++ b/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py @@ -181,7 +181,7 @@ def start_repost(account_repost_doc=str) -> None: if not repost_doc.delete_cancelled_entries: doc.make_gl_entries(1) doc.make_gl_entries() - else: + elif doc.doctype in frappe.get_hooks("repost_allowed_doctypes"): if hasattr(doc, "make_gl_entries") and callable(doc.make_gl_entries): if not repost_doc.delete_cancelled_entries: if "cancel" in inspect.getfullargspec(doc.make_gl_entries): From 13a3c816d742fe2b95cfa889b38d45ee88ea0acf Mon Sep 17 00:00:00 2001 From: Abdeali Chharchhoda Date: Mon, 23 Dec 2024 08:48:46 +0530 Subject: [PATCH 16/50] fix: Remove typo (cherry picked from commit ba28f6bf7331b3ef86a49fbcce959e601956a1a4) --- erpnext/accounts/doctype/bank_account/bank_account.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/bank_account/bank_account.py b/erpnext/accounts/doctype/bank_account/bank_account.py index c7c693a1cba7..4155f0edeef7 100644 --- a/erpnext/accounts/doctype/bank_account/bank_account.py +++ b/erpnext/accounts/doctype/bank_account/bank_account.py @@ -48,7 +48,7 @@ def autoname(self): self.name = self.account_name + " - " + self.bank def on_trash(self): - delete_contact_and_address("BankAccount", self.name) + delete_contact_and_address("Bank Account", self.name) def validate(self): self.validate_company() From e6390bfba1dca8c961029564c40b5ae1ae37878e Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Tue, 10 Dec 2024 14:28:22 +0100 Subject: [PATCH 17/50] fix: permissions for marking Quotation as lost (cherry picked from commit 4d5241486ffa426fe7b17be3354a93ae0896d730) # Conflicts: # erpnext/crm/doctype/competitor/competitor.json # erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.json --- .../crm/doctype/competitor/competitor.json | 27 ++++++++++++------- .../quotation_lost_reason.json | 20 ++++++++++++++ 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/erpnext/crm/doctype/competitor/competitor.json b/erpnext/crm/doctype/competitor/competitor.json index fd6da239212c..2348394d30e2 100644 --- a/erpnext/crm/doctype/competitor/competitor.json +++ b/erpnext/crm/doctype/competitor/competitor.json @@ -38,7 +38,11 @@ "table_fieldname": "competitors" } ], +<<<<<<< HEAD "modified": "2023-11-23 19:33:54.284279", +======= + "modified": "2024-12-10 08:26:38.496003", +>>>>>>> 4d5241486f (fix: permissions for marking Quotation as lost) "modified_by": "Administrator", "module": "CRM", "name": "Competitor", @@ -53,20 +57,25 @@ "print": 1, "read": 1, "report": 1, - "role": "System Manager", + "role": "Sales Master Manager", "share": 1, "write": 1 }, { - "create": 1, - "email": 1, - "export": 1, - "print": 1, "read": 1, - "report": 1, - "role": "Sales User", - "share": 1, - "write": 1 + "role": "Sales User" + }, + { + "read": 1, + "role": "Sales Manager" + }, + { + "read": 1, + "role": "Maintenance Manager" + }, + { + "read": 1, + "role": "Maintenance User" } ], "quick_entry": 1, diff --git a/erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.json b/erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.json index 0eae08e87077..e1eafb527e3a 100644 --- a/erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.json +++ b/erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.json @@ -32,7 +32,11 @@ "table_fieldname": "lost_reasons" } ], +<<<<<<< HEAD "modified": "2023-11-23 19:31:02.743353", +======= + "modified": "2024-12-10 08:21:38.280627", +>>>>>>> 4d5241486f (fix: permissions for marking Quotation as lost) "modified_by": "Administrator", "module": "Setup", "name": "Quotation Lost Reason", @@ -49,6 +53,22 @@ "role": "Sales Master Manager", "share": 1, "write": 1 + }, + { + "read": 1, + "role": "Sales User" + }, + { + "read": 1, + "role": "Sales Manager" + }, + { + "read": 1, + "role": "Maintenance User" + }, + { + "read": 1, + "role": "Maintenance Manager" } ], "quick_entry": 1, From 3d4a4e661c802c121594881b7357c9cf46023aa0 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 23 Dec 2024 11:14:27 +0530 Subject: [PATCH 18/50] chore: resolve conflicts --- erpnext/crm/doctype/competitor/competitor.json | 4 ---- .../doctype/quotation_lost_reason/quotation_lost_reason.json | 4 ---- 2 files changed, 8 deletions(-) diff --git a/erpnext/crm/doctype/competitor/competitor.json b/erpnext/crm/doctype/competitor/competitor.json index 2348394d30e2..021488ab99bd 100644 --- a/erpnext/crm/doctype/competitor/competitor.json +++ b/erpnext/crm/doctype/competitor/competitor.json @@ -38,11 +38,7 @@ "table_fieldname": "competitors" } ], -<<<<<<< HEAD - "modified": "2023-11-23 19:33:54.284279", -======= "modified": "2024-12-10 08:26:38.496003", ->>>>>>> 4d5241486f (fix: permissions for marking Quotation as lost) "modified_by": "Administrator", "module": "CRM", "name": "Competitor", diff --git a/erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.json b/erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.json index e1eafb527e3a..a0e0f176ddf0 100644 --- a/erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.json +++ b/erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.json @@ -32,11 +32,7 @@ "table_fieldname": "lost_reasons" } ], -<<<<<<< HEAD - "modified": "2023-11-23 19:31:02.743353", -======= "modified": "2024-12-10 08:21:38.280627", ->>>>>>> 4d5241486f (fix: permissions for marking Quotation as lost) "modified_by": "Administrator", "module": "Setup", "name": "Quotation Lost Reason", From 58e846709ec961d965c9b6bdaf5cec482b608305 Mon Sep 17 00:00:00 2001 From: Nicolas Pereira <41456803+hqnicolas@users.noreply.github.com> Date: Fri, 13 Dec 2024 01:51:30 -0300 Subject: [PATCH 19/50] fix: Stock Entry uses incorrect company when generated from Pick List (#44679) (cherry picked from commit 00898be8e4638ed88e30ace37b752d2a3b5887c2) (cherry picked from commit cd693b5fa48e552f7e7418a551a1e84ed7024c90) --- erpnext/stock/doctype/pick_list/pick_list.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py index ba1cc228bfa7..b48d479560d2 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.py +++ b/erpnext/stock/doctype/pick_list/pick_list.py @@ -1247,6 +1247,7 @@ def create_stock_entry(pick_list): stock_entry = frappe.new_doc("Stock Entry") stock_entry.pick_list = pick_list.get("name") stock_entry.purpose = pick_list.get("purpose") + stock_entry.company = pick_list.get("company") stock_entry.set_stock_entry_type() if pick_list.get("work_order"): From a55aaea5a15f9966635b4960547c62589ef32af2 Mon Sep 17 00:00:00 2001 From: ljain112 Date: Tue, 17 Dec 2024 17:54:08 +0530 Subject: [PATCH 20/50] fix: buying rate for service item in gross profit report (cherry picked from commit 8d6e79a16f52723da3b494a2e863f8e77d4419ac) --- erpnext/accounts/report/gross_profit/gross_profit.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 647490dcc905..a27503e8b6db 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -748,12 +748,13 @@ def get_last_purchase_rate(self, item_code, row): .inner_join(purchase_invoice) .on(purchase_invoice.name == purchase_invoice_item.parent) .select( - purchase_invoice.name, purchase_invoice_item.base_rate / purchase_invoice_item.conversion_factor, ) .where(purchase_invoice.docstatus == 1) .where(purchase_invoice.posting_date <= self.filters.to_date) .where(purchase_invoice_item.item_code == item_code) + .where(purchase_invoice.is_return == 0) + .where(purchase_invoice_item.parenttype == "Purchase Invoice") ) if row.project: From 875797e655db4a67696ed6eae963705be5ebaa68 Mon Sep 17 00:00:00 2001 From: ljain112 Date: Thu, 19 Dec 2024 12:04:04 +0530 Subject: [PATCH 21/50] fix: correct args for get_advance_payment_entries_for_regional (cherry picked from commit df13a4cc2f3167ff322379227f5382fc8045a417) --- erpnext/controllers/accounts_controller.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index e1a7d5803c9a..6932a4b47d90 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1214,6 +1214,8 @@ def set_advances(self): def get_advance_entries(self, include_unallocated=True): party_account = [] + default_advance_account = None + if self.doctype == "Sales Invoice": party_type = "Customer" party = self.customer @@ -1229,10 +1231,14 @@ def get_advance_entries(self, include_unallocated=True): order_doctype = "Purchase Order" party_account.append(self.credit_to) - party_account.extend( - get_party_account(party_type, party=party, company=self.company, include_advance=True) + party_accounts = get_party_account( + party_type, party=party, company=self.company, include_advance=True ) + if party_accounts: + party_account.append(party_accounts[0]) + default_advance_account = party_accounts[1] if len(party_accounts) == 2 else None + order_list = list(set(d.get(order_field) for d in self.get("items") if d.get(order_field))) journal_entries = get_advance_journal_entries( @@ -1240,7 +1246,13 @@ def get_advance_entries(self, include_unallocated=True): ) payment_entries = get_advance_payment_entries_for_regional( - party_type, party, party_account, order_doctype, order_list, include_unallocated + party_type, + party, + party_account, + order_doctype, + order_list, + default_advance_account, + include_unallocated, ) res = journal_entries + payment_entries From 497029f958c0c7167422c32edbd50c080eeaff33 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:38:21 +0530 Subject: [PATCH 22/50] fix: incorrect Material Transferred for Manufacturing qty (backport #44823) (#44832) * fix: incorrect Material Transferred for Manufacturing qty (#44823) (cherry picked from commit fe0036e707252f5842444a5cb728410cb81fe6ca) # Conflicts: # erpnext/manufacturing/doctype/job_card/job_card.py * chore: fix conflicts --------- Co-authored-by: rohitwaghchaure --- .../doctype/job_card/job_card.py | 5 +- .../doctype/work_order/test_work_order.py | 55 +++++++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index 586371090770..011df3258eed 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -944,8 +944,9 @@ def set_transferred_qty(self, update_status=False): if doc.transfer_material_against == "Job Card" and not doc.skip_transfer: min_qty = [] for d in doc.operations: - if d.completed_qty: - min_qty.append(d.completed_qty) + completed_qty = flt(d.completed_qty) + flt(d.process_loss_qty) + if completed_qty: + min_qty.append(completed_qty) else: min_qty = [] break diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index 6ee3f73eb084..f8ddf0074283 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -7,6 +7,7 @@ from frappe.utils import add_days, add_months, add_to_date, cint, flt, now, today from erpnext.manufacturing.doctype.job_card.job_card import JobCardCancelError +from erpnext.manufacturing.doctype.job_card.job_card import make_stock_entry as make_stock_entry_from_jc from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom from erpnext.manufacturing.doctype.work_order.work_order import ( CapacityError, @@ -505,6 +506,60 @@ def test_job_card(self): for stock_entry in stock_entries: stock_entry.cancel() + def test_work_order_material_transferred_qty_with_process_loss(self): + stock_entries = [] + bom = frappe.get_doc("BOM", {"docstatus": 1, "with_operations": 1, "company": "_Test Company"}) + + work_order = make_wo_order_test_record( + item=bom.item, + qty=2, + bom_no=bom.name, + source_warehouse="_Test Warehouse - _TC", + transfer_material_against="Job Card", + ) + + self.assertEqual(work_order.qty, 2) + + for row in work_order.required_items: + stock_entry_doc = test_stock_entry.make_stock_entry( + item_code=row.item_code, target="_Test Warehouse - _TC", qty=row.required_qty, basic_rate=100 + ) + stock_entries.append(stock_entry_doc) + + job_cards = frappe.get_all( + "Job Card", filters={"work_order": work_order.name}, order_by="creation asc" + ) + + for row in job_cards: + transfer_entry_1 = make_stock_entry_from_jc(row.name) + transfer_entry_1.submit() + + doc = frappe.get_doc("Job Card", row.name) + for row in doc.scheduled_time_logs: + doc.append( + "time_logs", + { + "from_time": row.from_time, + "to_time": row.to_time, + "time_in_mins": row.time_in_mins, + "completed_qty": 1, + }, + ) + + doc.save() + doc.submit() + + self.assertEqual(doc.total_completed_qty, 1) + self.assertEqual(doc.process_loss_qty, 1) + + work_order.reload() + + self.assertEqual(work_order.material_transferred_for_manufacturing, 2) + + for row in work_order.operations: + self.assertEqual(row.completed_qty, 1) + self.assertEqual(row.process_loss_qty, 1) + def test_capcity_planning(self): frappe.db.set_single_value( "Manufacturing Settings", {"disable_capacity_planning": 0, "capacity_planning_for_days": 1} From bec1f972b36c33b76317fd286370834f71504797 Mon Sep 17 00:00:00 2001 From: rs-rethik Date: Fri, 20 Dec 2024 12:07:20 +0530 Subject: [PATCH 23/50] feat: add difference_posting_date field (cherry picked from commit 225e56cbcae5c30172b52aa2e6cbc04a5ec01d43) # Conflicts: # erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json # erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json --- .../purchase_invoice_advance.json | 18 +++++++++++++++--- .../purchase_invoice_advance.py | 1 + .../sales_invoice_advance.json | 18 +++++++++++++++--- .../sales_invoice_advance.py | 1 + 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json b/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json index 4db531eac906..5cb780b3e6fb 100644 --- a/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json +++ b/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json @@ -14,7 +14,8 @@ "advance_amount", "allocated_amount", "exchange_gain_loss", - "ref_exchange_rate" + "ref_exchange_rate", + "difference_posting_date" ], "fields": [ { @@ -30,7 +31,7 @@ "width": "180px" }, { - "columns": 3, + "columns": 2, "fieldname": "reference_name", "fieldtype": "Dynamic Link", "in_list_view": 1, @@ -40,7 +41,7 @@ "read_only": 1 }, { - "columns": 3, + "columns": 2, "fieldname": "remarks", "fieldtype": "Text", "in_list_view": 1, @@ -111,13 +112,24 @@ "label": "Reference Exchange Rate", "non_negative": 1, "read_only": 1 + }, + { + "columns": 2, + "fieldname": "difference_posting_date", + "fieldtype": "Date", + "in_list_view": 1, + "label": "Difference Posting Date" } ], "idx": 1, "index_web_pages_for_search": 1, "istable": 1, "links": [], +<<<<<<< HEAD "modified": "2023-06-23 21:13:18.013816", +======= + "modified": "2024-12-20 12:04:46.729972", +>>>>>>> 225e56cbca (feat: add difference_posting_date field) "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice Advance", diff --git a/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.py b/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.py index bbd3009224a0..a3fabbdc322f 100644 --- a/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.py +++ b/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.py @@ -16,6 +16,7 @@ class PurchaseInvoiceAdvance(Document): advance_amount: DF.Currency allocated_amount: DF.Currency + difference_posting_date: DF.Date | None exchange_gain_loss: DF.Currency parent: DF.Data parentfield: DF.Data diff --git a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json index 0ae85d900049..151d493ed098 100644 --- a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json +++ b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json @@ -14,7 +14,8 @@ "advance_amount", "allocated_amount", "exchange_gain_loss", - "ref_exchange_rate" + "ref_exchange_rate", + "difference_posting_date" ], "fields": [ { @@ -30,7 +31,7 @@ "width": "250px" }, { - "columns": 3, + "columns": 2, "fieldname": "reference_name", "fieldtype": "Dynamic Link", "in_list_view": 1, @@ -41,7 +42,7 @@ "read_only": 1 }, { - "columns": 3, + "columns": 2, "fieldname": "remarks", "fieldtype": "Text", "in_list_view": 1, @@ -112,13 +113,24 @@ "label": "Reference Exchange Rate", "non_negative": 1, "read_only": 1 + }, + { + "columns": 2, + "fieldname": "difference_posting_date", + "fieldtype": "Date", + "in_list_view": 1, + "label": "Difference Posting Date" } ], "idx": 1, "index_web_pages_for_search": 1, "istable": 1, "links": [], +<<<<<<< HEAD "modified": "2023-06-23 21:12:57.557731", +======= + "modified": "2024-12-20 11:58:28.962370", +>>>>>>> 225e56cbca (feat: add difference_posting_date field) "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice Advance", diff --git a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.py b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.py index 5eeedb25f29a..1d115c5c5073 100644 --- a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.py +++ b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.py @@ -16,6 +16,7 @@ class SalesInvoiceAdvance(Document): advance_amount: DF.Currency allocated_amount: DF.Currency + difference_posting_date: DF.Date | None exchange_gain_loss: DF.Currency parent: DF.Data parentfield: DF.Data From 7498cdf644960525f09b07cc829a09f704a22b4b Mon Sep 17 00:00:00 2001 From: rs-rethik Date: Fri, 20 Dec 2024 12:10:08 +0530 Subject: [PATCH 24/50] feat: use difference_posting_date for journal entry posting_date (cherry picked from commit ff1d040a6e1aa80c3b93835395db31a222dd5568) --- erpnext/controllers/accounts_controller.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 6932a4b47d90..b15788d8fcc7 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1204,6 +1204,7 @@ def set_advances(self): "advance_amount": flt(d.amount), "allocated_amount": allocated_amount, "ref_exchange_rate": flt(d.exchange_rate), # exchange_rate of advance entry + "difference_posting_date": self.posting_date, } if d.get("paid_from"): advance_row["account"] = d.paid_from @@ -1509,7 +1510,6 @@ def make_exchange_gain_loss_journal( gain_loss_account = frappe.get_cached_value( "Company", self.company, "exchange_gain_loss_account" ) - je = create_gain_loss_journal( self.company, args.get("difference_posting_date") if args else self.posting_date, @@ -1595,6 +1595,7 @@ def update_against_document_in_jv(self): "Company", self.company, "exchange_gain_loss_account" ), "exchange_gain_loss": flt(d.get("exchange_gain_loss")), + "difference_posting_date": d.get("difference_posting_date"), } ) lst.append(args) From 4884849f23c8a27661a540c0cb2c7c26d588aa08 Mon Sep 17 00:00:00 2001 From: rs-rethik Date: Fri, 20 Dec 2024 12:13:35 +0530 Subject: [PATCH 25/50] test: add unit test to validate journal entry posting date (cherry picked from commit c14a2d73bf10fd910e319bc62c2d8e117cce73f1) --- .../tests/test_accounts_controller.py | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/erpnext/controllers/tests/test_accounts_controller.py b/erpnext/controllers/tests/test_accounts_controller.py index 289a955f9801..069eae553154 100644 --- a/erpnext/controllers/tests/test_accounts_controller.py +++ b/erpnext/controllers/tests/test_accounts_controller.py @@ -2,6 +2,8 @@ # For license information, please see license.txt +from datetime import datetime + import frappe from frappe import qb from frappe.query_builder.functions import Sum @@ -1979,3 +1981,94 @@ def test_71_advance_payment_against_purchase_invoice_in_foreign_currency(self): self.assertEqual(len(exc_je_for_adv), 0) self.remove_advance_accounts_from_party_master() + + def test_difference_posting_date_in_pi_and_si(self): + self.setup_advance_accounts_in_party_master() + + # create payment entry for customer + adv = self.create_payment_entry(amount=1, source_exc_rate=83) + adv.save() + self.assertEqual(adv.paid_from, self.advance_received_usd) + adv.submit() + + # create sales invoice with advance received + si = self.create_sales_invoice(qty=1, conversion_rate=80, rate=1, do_not_submit=True) + si.debit_to = self.debtors_usd + si.append( + "advances", + { + "reference_type": "Payment Entry", + "reference_name": "ACC-PAY-2024-00001", + "remarks": "Amount INR 1 received from _Test MC Customer USD\nTransaction reference no Test001 dated 2024-12-19", + "advance_amount": 1.0, + "allocated_amount": 1.0, + "exchange_gain_loss": 3.0, + "ref_exchange_rate": 83.0, + "difference_posting_date": add_days(nowdate(), -2), + }, + ) + si.save().submit() + + # exc Gain/Loss journal should've been creatad + exc_je_for_si = self.get_journals_for(si.doctype, si.name) + exc_je_for_adv = self.get_journals_for(adv.doctype, adv.name) + self.assertEqual(len(exc_je_for_si), 1) + self.assertEqual(len(exc_je_for_adv), 1) + self.assertEqual(exc_je_for_si, exc_je_for_adv) + + # check jv created with difference_posting_date in sales invoice + jv = frappe.get_doc("Journal Entry", exc_je_for_si[0].parent) + sales_invoice = frappe.get_doc("Sales Invoice", si.name) + self.assertEqual(sales_invoice.advances[0].difference_posting_date, jv.posting_date) + + # create payment entry for supplier + usd_amount = 1 + inr_amount = 85 + exc_rate = 85 + adv = create_payment_entry( + company=self.company, + payment_type="Pay", + party_type="Supplier", + party=self.supplier, + paid_from=self.cash, + paid_to=self.advance_paid_usd, + paid_amount=inr_amount, + ) + adv.source_exchange_rate = 1 + adv.target_exchange_rate = exc_rate + adv.received_amount = usd_amount + adv.paid_amount = exc_rate * usd_amount + adv.posting_date = nowdate() + adv.save() + self.assertEqual(adv.paid_to, self.advance_paid_usd) + adv.submit() + + # create purchase invoice with advance paid + pi = self.create_purchase_invoice(qty=1, conversion_rate=80, rate=1, do_not_submit=True) + pi.append( + "advances", + { + "reference_type": "Payment Entry", + "reference_name": "ACC-PAY-2024-00002", + "remarks": "Amount INR 1 paid to _Test MC Supplier USD\nTransaction reference no Test001 dated 2024-12-20", + "advance_amount": 1.0, + "allocated_amount": 1.0, + "exchange_gain_loss": 5.0, + "ref_exchange_rate": 85.0, + "difference_posting_date": add_days(nowdate(), -2), + }, + ) + pi.save().submit() + self.assertEqual(pi.credit_to, self.creditors_usd) + + # exc Gain/Loss journal should've been creatad + exc_je_for_pi = self.get_journals_for(pi.doctype, pi.name) + exc_je_for_adv = self.get_journals_for(adv.doctype, adv.name) + self.assertEqual(len(exc_je_for_pi), 1) + self.assertEqual(len(exc_je_for_adv), 1) + self.assertEqual(exc_je_for_pi, exc_je_for_adv) + + # check jv created with difference_posting_date in purchase invoice + journal_voucher = frappe.get_doc("Journal Entry", exc_je_for_pi[0].parent) + purchase_invoice = frappe.get_doc("Purchase Invoice", pi.name) + self.assertEqual(purchase_invoice.advances[0].difference_posting_date, journal_voucher.posting_date) From 13123a04121258e27b6692a03c6004cd244c7b35 Mon Sep 17 00:00:00 2001 From: rs-rethik Date: Fri, 20 Dec 2024 12:42:47 +0530 Subject: [PATCH 26/50] refactor: convert sql query to query builder (cherry picked from commit 2d58e845e633943bae2d481f66d200b16ab91bdf) --- erpnext/controllers/accounts_controller.py | 34 +++++++++++----------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index b15788d8fcc7..e5b5887e3ed2 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -379,13 +379,14 @@ def on_trash(self): == 1 ) ).run() - frappe.db.sql( - "delete from `tabGL Entry` where voucher_type=%s and voucher_no=%s", (self.doctype, self.name) - ) - frappe.db.sql( - "delete from `tabStock Ledger Entry` where voucher_type=%s and voucher_no=%s", - (self.doctype, self.name), - ) + gle = frappe.qb.DocType("GL Entry") + frappe.qb.from_(gle).delete().where( + (gle.voucher_type == self.doctype) & (gle.voucher_no == self.name) + ).run() + sle = frappe.qb.DocType("Stock Ledger Entry") + frappe.qb.from_(gle).delete().where( + (sle.voucher_type == self.doctype) & (sle.voucher_no == self.name) + ).run() def remove_serial_and_batch_bundle(self): bundles = frappe.get_all( @@ -1150,11 +1151,12 @@ def validate_account_currency(self, account, account_currency=None): def clear_unallocated_advances(self, childtype, parentfield): self.set(parentfield, self.get(parentfield, {"allocated_amount": ["not in", [0, None, ""]]})) - frappe.db.sql( - """delete from `tab{}` where parentfield={} and parent = {} - and allocated_amount = 0""".format(childtype, "%s", "%s"), - (parentfield, self.name), - ) + doctype = frappe.qb.DocType(childtype) + frappe.qb.from_(doctype).delete().where( + (doctype.parentfield == parentfield) + & (doctype.parent == self.name) + & (doctype.allocated_amount == 0) + ).run() @frappe.whitelist() def apply_shipping_rule(self): @@ -2129,11 +2131,9 @@ def delink_advance_entries(self, linked_doc_name): for adv in self.advances: consider_for_total_advance = True if adv.reference_name == linked_doc_name: - frappe.db.sql( - f"""delete from `tab{self.doctype} Advance` - where name = %s""", - adv.name, - ) + doctype = frappe.qb.DocType(self.doctype + " Advance") + frappe.qb.from_(doctype).delete().where(doctype.name == adv.name).run() + consider_for_total_advance = False if consider_for_total_advance: From 3ab4acfafaa79295b6c56d9c6a03ccfe78f2e9c0 Mon Sep 17 00:00:00 2001 From: rs-rethik Date: Fri, 20 Dec 2024 14:00:54 +0530 Subject: [PATCH 27/50] fix: update query (cherry picked from commit 854e37c05c454ad2d93ec0f4a70600f2ca7d5eec) --- erpnext/controllers/accounts_controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index e5b5887e3ed2..20b5885bfdcc 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -384,7 +384,7 @@ def on_trash(self): (gle.voucher_type == self.doctype) & (gle.voucher_no == self.name) ).run() sle = frappe.qb.DocType("Stock Ledger Entry") - frappe.qb.from_(gle).delete().where( + frappe.qb.from_(sle).delete().where( (sle.voucher_type == self.doctype) & (sle.voucher_no == self.name) ).run() From cf4068d1a384a6c43c5d9e08e1cfdce7a9519cdd Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 23 Dec 2024 14:10:44 +0530 Subject: [PATCH 28/50] chore: resolve conflicts --- .../purchase_invoice_advance/purchase_invoice_advance.json | 4 ---- .../doctype/sales_invoice_advance/sales_invoice_advance.json | 4 ---- 2 files changed, 8 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json b/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json index 5cb780b3e6fb..4d0579ebc7e4 100644 --- a/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json +++ b/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json @@ -125,11 +125,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], -<<<<<<< HEAD - "modified": "2023-06-23 21:13:18.013816", -======= "modified": "2024-12-20 12:04:46.729972", ->>>>>>> 225e56cbca (feat: add difference_posting_date field) "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice Advance", diff --git a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json index 151d493ed098..1246d04d3d68 100644 --- a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json +++ b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json @@ -126,11 +126,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], -<<<<<<< HEAD - "modified": "2023-06-23 21:12:57.557731", -======= "modified": "2024-12-20 11:58:28.962370", ->>>>>>> 225e56cbca (feat: add difference_posting_date field) "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice Advance", From 4c5540aef9232d044b9a0bd3de278a3b04222230 Mon Sep 17 00:00:00 2001 From: vishakhdesai Date: Fri, 20 Dec 2024 18:03:42 +0530 Subject: [PATCH 29/50] fix: update correct cost center in Accounts Receivable Report (cherry picked from commit 09776e9a5ab6221329b3f6e8e3ad94aee0e43d5d) --- .../accounts/report/accounts_receivable/accounts_receivable.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index 1d67109d68df..0d70225c9190 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -150,6 +150,9 @@ def init_voucher_balance(self): if key not in self.voucher_balance: self.voucher_balance[key] = self.build_voucher_dict(ple) + if ple.voucher_type == ple.against_voucher_type and ple.voucher_no == ple.against_voucher_no: + self.voucher_balance[key].cost_center = ple.cost_center + self.get_invoices(ple) if self.filters.get("group_by_party"): From 19a8ea217ef9252c2ed78fb6f55a501f525276e7 Mon Sep 17 00:00:00 2001 From: vishakhdesai Date: Fri, 20 Dec 2024 18:41:51 +0530 Subject: [PATCH 30/50] fix: do not set cost_center update_voucher_balance as it is set in init_voucher_balance (cherry picked from commit 3b36ce560c1faeeff93c428a589522138ab364d2) --- .../report/accounts_receivable/accounts_receivable.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index 0d70225c9190..1ddf9bce06f7 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -134,7 +134,6 @@ def build_voucher_dict(self, ple): paid_in_account_currency=0.0, credit_note_in_account_currency=0.0, outstanding_in_account_currency=0.0, - cost_center=ple.cost_center, ) def init_voucher_balance(self): @@ -278,9 +277,6 @@ def update_voucher_balance(self, ple): row.paid -= amount row.paid_in_account_currency -= amount_in_account_currency - if not row.cost_center and ple.cost_center: - row.cost_center = str(ple.cost_center) - def update_sub_total_row(self, row, party): total_row = self.total_row_map.get(party) From f005bef218d96d7be929d2db9d3cf476e5477d4a Mon Sep 17 00:00:00 2001 From: venkat102 Date: Tue, 17 Dec 2024 13:15:02 +0530 Subject: [PATCH 31/50] chore: use get function (cherry picked from commit 1663c7983eac8112b535c467ca9c3845f94bb577) --- .../tax_withholding_category/tax_withholding_category.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py index 69c7eb1153c5..9a690a261228 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py +++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py @@ -539,7 +539,7 @@ def get_tds_amount(ldc, parties, inv, tax_details, vouchers): ) supp_credit_amt = supp_jv_credit_amt - supp_credit_amt += inv.tax_withholding_net_total + supp_credit_amt += inv.get("tax_withholding_net_total", 0) for type in payment_entry_amounts: if type.payment_type == "Pay": @@ -551,9 +551,9 @@ def get_tds_amount(ldc, parties, inv, tax_details, vouchers): cumulative_threshold = tax_details.get("cumulative_threshold", 0) if inv.doctype != "Payment Entry": - tax_withholding_net_total = inv.base_tax_withholding_net_total + tax_withholding_net_total = inv.get("base_tax_withholding_net_total", 0) else: - tax_withholding_net_total = inv.tax_withholding_net_total + tax_withholding_net_total = inv.get("tax_withholding_net_total", 0) if (threshold and tax_withholding_net_total >= threshold) or ( cumulative_threshold and (supp_credit_amt + supp_inv_credit_amt) >= cumulative_threshold From 8f8dd1c088823dd55013da7c79caf58afd73dc11 Mon Sep 17 00:00:00 2001 From: venkat102 Date: Tue, 17 Dec 2024 13:15:41 +0530 Subject: [PATCH 32/50] fix: fetch tax withholding category from the voucher (cherry picked from commit 09e64594dbd694e4a77b287a08d4e44fd2bc6aba) --- .../report/tax_withholding_details/tax_withholding_details.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py index d6e0af0b5da8..42c6c82b19f3 100644 --- a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py +++ b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py @@ -405,7 +405,7 @@ def get_doc_info(vouchers, doctype, tax_category_map, net_total_map=None): "paid_amount_after_tax", "base_paid_amount", ], - "Journal Entry": ["total_debit"], + "Journal Entry": ["tax_withholding_category", "total_debit"], } entries = frappe.get_all( From 01c1ed98ac3883620ed1c9ebc21eaaf6fd8e8f76 Mon Sep 17 00:00:00 2001 From: Nijith anil <83776819+nijithanil@users.noreply.github.com> Date: Mon, 23 Dec 2024 14:48:32 +0530 Subject: [PATCH 33/50] fix(ux): purchase invoice link in error message (#44797) * fix(ux): purchase invoice link in error message * chore: fix linter --------- Co-authored-by: ruthra kumar (cherry picked from commit 6f00a87a9c3036d450dbae22fed53ba8a420b0db) --- .../accounts/doctype/purchase_invoice/purchase_invoice.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index ebc4efc08a0e..dc6ee6c1469d 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -1677,7 +1677,12 @@ def validate_supplier_invoice(self): if pi: pi = pi[0][0] - frappe.throw(_("Supplier Invoice No exists in Purchase Invoice {0}").format(pi)) + + frappe.throw( + _("Supplier Invoice No exists in Purchase Invoice {0}").format( + get_link_to_form("Purchase Invoice", pi) + ) + ) def update_billing_status_in_pr(self, update_modified=True): if self.is_return and not self.update_billed_amount_in_purchase_receipt: From 33fc987d95283f76dea8dc77e4fa7856a1b4f485 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 23 Dec 2024 14:49:42 +0530 Subject: [PATCH 34/50] refactor(test): remove hardcoded names --- erpnext/controllers/tests/test_accounts_controller.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/erpnext/controllers/tests/test_accounts_controller.py b/erpnext/controllers/tests/test_accounts_controller.py index 069eae553154..e557a6b2d79c 100644 --- a/erpnext/controllers/tests/test_accounts_controller.py +++ b/erpnext/controllers/tests/test_accounts_controller.py @@ -1990,6 +1990,7 @@ def test_difference_posting_date_in_pi_and_si(self): adv.save() self.assertEqual(adv.paid_from, self.advance_received_usd) adv.submit() + adv.reload() # create sales invoice with advance received si = self.create_sales_invoice(qty=1, conversion_rate=80, rate=1, do_not_submit=True) @@ -1997,8 +1998,8 @@ def test_difference_posting_date_in_pi_and_si(self): si.append( "advances", { - "reference_type": "Payment Entry", - "reference_name": "ACC-PAY-2024-00001", + "reference_type": adv.doctype, + "reference_name": adv.name, "remarks": "Amount INR 1 received from _Test MC Customer USD\nTransaction reference no Test001 dated 2024-12-19", "advance_amount": 1.0, "allocated_amount": 1.0, @@ -2048,8 +2049,8 @@ def test_difference_posting_date_in_pi_and_si(self): pi.append( "advances", { - "reference_type": "Payment Entry", - "reference_name": "ACC-PAY-2024-00002", + "reference_type": adv.doctype, + "reference_name": adv.name, "remarks": "Amount INR 1 paid to _Test MC Supplier USD\nTransaction reference no Test001 dated 2024-12-20", "advance_amount": 1.0, "allocated_amount": 1.0, From 2edb6f3224fd064beaf31dbf722f08ddf68c146c Mon Sep 17 00:00:00 2001 From: ljain112 Date: Mon, 16 Dec 2024 16:20:36 +0530 Subject: [PATCH 35/50] fix: avg. buying amount for product bundle item with serial and batch no in gross profit report (cherry picked from commit cc3f4bb0b04f56f33f290114d4c18594bd9f3eef) --- erpnext/accounts/report/gross_profit/gross_profit.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index a27503e8b6db..5df37603b9a9 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -637,6 +637,7 @@ def get_buying_amount_from_product_bundle(self, row, product_bundle): packed_item_row = row.copy() packed_item_row.warehouse = packed_item.warehouse packed_item_row.qty = packed_item.total_qty * -1 + packed_item_row.serial_and_batch_bundle = packed_item.serial_and_batch_bundle buying_amount += self.get_buying_amount(packed_item_row, packed_item.item_code) return flt(buying_amount, self.currency_precision) @@ -728,6 +729,7 @@ def get_average_buying_rate(self, row, item_code): "voucher_no": row.parent, "allow_zero_valuation": True, "company": self.filters.company, + "item_code": item_code, } ) @@ -997,6 +999,7 @@ def get_bundle_item_row(self, row, item): "is_return": row.is_return, "cost_center": row.cost_center, "invoice": row.parent, + "serial_and_batch_bundle": row.serial_and_batch_bundle, } ) @@ -1048,6 +1051,7 @@ def load_product_bundle(self): pki.rate, (pki.rate * pki.qty).as_("base_amount"), pki.parent_detail_docname, + pki.serial_and_batch_bundle, ) .where(pki.docstatus == 1) ) From 0969877cd7c30d997f5f42de1d8a7197846d07de Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 18:11:53 +0530 Subject: [PATCH 36/50] fix: incoming rate should be zero for rejected items (backport #44857) (#44859) fix: incoming rate should be zero for rejected items (#44857) (cherry picked from commit a515a399cf7778b8a5fa430b11188fe9b677024d) Co-authored-by: rohitwaghchaure --- .../purchase_invoice/test_purchase_invoice.py | 46 +++++++++++++++++++ .../purchase_receipt/purchase_receipt.py | 5 ++ 2 files changed, 51 insertions(+) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index e353435661c4..76fbfd2f4e27 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -1838,6 +1838,52 @@ def test_adjust_incoming_rate(self): frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 1) + def test_adjust_incoming_rate_for_rejected_item(self): + frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 0) + + frappe.db.set_single_value("Buying Settings", "set_landed_cost_based_on_purchase_invoice_rate", 1) + + # Cost of Item is zero in Purchase Receipt + pr = make_purchase_receipt(qty=1, rejected_qty=1, rate=0) + + stock_value_difference = frappe.db.get_value( + "Stock Ledger Entry", + {"voucher_type": "Purchase Receipt", "voucher_no": pr.name}, + "stock_value_difference", + ) + self.assertEqual(stock_value_difference, 0) + + pi = create_purchase_invoice_from_receipt(pr.name) + for row in pi.items: + row.qty = 1 + row.rate = 150 + + pi.save() + pi.submit() + + stock_value_difference = frappe.db.get_value( + "Stock Ledger Entry", + {"voucher_type": "Purchase Receipt", "voucher_no": pr.name, "warehouse": pi.items[0].warehouse}, + "stock_value_difference", + ) + self.assertEqual(stock_value_difference, 150) + + stock_value_difference = frappe.db.get_value( + "Stock Ledger Entry", + { + "voucher_type": "Purchase Receipt", + "voucher_no": pr.name, + "warehouse": pi.items[0].rejected_warehouse, + }, + "stock_value_difference", + ) + + self.assertFalse(stock_value_difference) + + frappe.db.set_single_value("Buying Settings", "set_landed_cost_based_on_purchase_invoice_rate", 0) + + frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 1) + def test_item_less_defaults(self): pi = frappe.new_doc("Purchase Invoice") pi.supplier = "_Test Supplier" diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 76ecf0fd596a..22d7012cc8b6 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -920,12 +920,17 @@ def reserve_stock_for_sales_order(self): ) def enable_recalculate_rate_in_sles(self): + rejected_warehouses = frappe.get_all( + "Purchase Receipt Item", filters={"parent": self.name}, pluck="rejected_warehouse" + ) + sle_table = frappe.qb.DocType("Stock Ledger Entry") ( frappe.qb.update(sle_table) .set(sle_table.recalculate_rate, 1) .where(sle_table.voucher_no == self.name) .where(sle_table.voucher_type == "Purchase Receipt") + .where(sle_table.warehouse.notin(rejected_warehouses)) ).run() From 3f3df7ef2a09d2ce9348b85448bc934eb5b49acf Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 19:15:32 +0530 Subject: [PATCH 37/50] perf: slow query related to stock ledger entry (backport #44861) (#44862) perf: slow query related to stock ledger entry (#44861) (cherry picked from commit 54d7b742ab98ef8fea26913f7d8a301cccc5a917) Co-authored-by: rohitwaghchaure --- .../stock/doctype/stock_ledger_entry/stock_ledger_entry.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json index d9af64c3983a..66fa6064129c 100644 --- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json +++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json @@ -124,6 +124,7 @@ "options": "DocType", "print_width": "150px", "read_only": 1, + "search_index": 1, "width": "150px" }, { @@ -362,7 +363,7 @@ "in_create": 1, "index_web_pages_for_search": 1, "links": [], - "modified": "2024-08-27 09:28:03.961443", + "modified": "2024-12-23 18:03:05.171023", "modified_by": "Administrator", "module": "Stock", "name": "Stock Ledger Entry", From 8092d58d9c36d263a2218fa7b4e95636706faf77 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 19:15:46 +0530 Subject: [PATCH 38/50] fix: do not validate qc for scrap item (backport #44844) (#44853) fix: do not validate qc for scrap item (#44844) (cherry picked from commit a2c2b8b5ad1b9d991b5c5380860e271a01ab012f) Co-authored-by: rohitwaghchaure --- erpnext/controllers/stock_controller.py | 3 + .../doctype/stock_entry/test_stock_entry.py | 74 +++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index c1cb83657da9..34556f725d41 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -999,6 +999,9 @@ def validate_inspection(self): elif self.doctype == "Stock Entry" and row.t_warehouse: qi_required = True # inward stock needs inspection + if row.get("is_scrap_item"): + continue + if qi_required: # validate row only if inspection is required on item level self.validate_qi_presence(row) if self.docstatus == 1: diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index a26940462bf1..05661d3a83a2 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -970,6 +970,80 @@ def test_nagative_stock_for_batch(self): self.assertRaises(frappe.ValidationError, ste.submit) + def test_quality_check_for_scrap_item(self): + from erpnext.manufacturing.doctype.work_order.work_order import ( + make_stock_entry as _make_stock_entry, + ) + + scrap_item = "_Test Scrap Item 1" + make_item(scrap_item, {"is_stock_item": 1, "is_purchase_item": 0}) + + bom_name = frappe.db.get_value("BOM Scrap Item", {"docstatus": 1}, "parent") + production_item = frappe.db.get_value("BOM", bom_name, "item") + + work_order = frappe.new_doc("Work Order") + work_order.production_item = production_item + work_order.update( + { + "company": "_Test Company", + "fg_warehouse": "_Test Warehouse 1 - _TC", + "production_item": production_item, + "bom_no": bom_name, + "qty": 1.0, + "stock_uom": frappe.db.get_value("Item", production_item, "stock_uom"), + "skip_transfer": 1, + } + ) + + work_order.get_items_and_operations_from_bom() + work_order.submit() + + stock_entry = frappe.get_doc(_make_stock_entry(work_order.name, "Manufacture", 1)) + for row in stock_entry.items: + if row.s_warehouse: + make_stock_entry( + item_code=row.item_code, + target=row.s_warehouse, + qty=row.qty, + basic_rate=row.basic_rate or 100, + ) + + if row.is_scrap_item: + row.item_code = scrap_item + row.uom = frappe.db.get_value("Item", scrap_item, "stock_uom") + row.stock_uom = frappe.db.get_value("Item", scrap_item, "stock_uom") + + stock_entry.inspection_required = 1 + stock_entry.save() + + self.assertTrue([row.item_code for row in stock_entry.items if row.is_scrap_item]) + + for row in stock_entry.items: + if not row.is_scrap_item: + qc = frappe.get_doc( + { + "doctype": "Quality Inspection", + "reference_name": stock_entry.name, + "inspected_by": "Administrator", + "reference_type": "Stock Entry", + "inspection_type": "In Process", + "status": "Accepted", + "sample_size": 1, + "item_code": row.item_code, + } + ) + + qc_name = qc.submit() + row.quality_inspection = qc_name + + stock_entry.reload() + stock_entry.submit() + for row in stock_entry.items: + if row.is_scrap_item: + self.assertFalse(row.quality_inspection) + else: + self.assertTrue(row.quality_inspection) + def test_quality_check(self): item_code = "_Test Item For QC" if not frappe.db.exists("Item", item_code): From f32cf84413dc4466ad77a320667e296c1344b160 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 22:30:58 +0530 Subject: [PATCH 39/50] fix: Warehouse wise Stock Value chart roles (backport #44865) (#44867) fix: Warehouse wise Stock Value chart roles (#44865) (cherry picked from commit 7d41805d0e91d681a92b292946f1d63c54f11dd0) Co-authored-by: rohitwaghchaure --- .../warehouse_wise_stock_value.json | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/dashboard_chart/warehouse_wise_stock_value/warehouse_wise_stock_value.json b/erpnext/stock/dashboard_chart/warehouse_wise_stock_value/warehouse_wise_stock_value.json index a07b55382ca2..400ec5e0e640 100644 --- a/erpnext/stock/dashboard_chart/warehouse_wise_stock_value/warehouse_wise_stock_value.json +++ b/erpnext/stock/dashboard_chart/warehouse_wise_stock_value/warehouse_wise_stock_value.json @@ -1,19 +1,37 @@ { "chart_name": "Warehouse wise Stock Value", "chart_type": "Custom", - "creation": "2020-07-20 21:01:04.296157", + "creation": "2022-03-30 00:58:02.018824", "docstatus": 0, "doctype": "Dashboard Chart", "filters_json": "{}", "idx": 0, "is_public": 1, "is_standard": 1, - "modified": "2020-07-22 13:01:01.815123", + "last_synced_on": "2024-12-23 18:44:46.822164", + "modified": "2024-12-23 19:31:17.003946", "modified_by": "Administrator", "module": "Stock", "name": "Warehouse wise Stock Value", "number_of_groups": 0, "owner": "Administrator", + "roles": [ + { + "role": "Sales Manager" + }, + { + "role": "Accounts Manager" + }, + { + "role": "Stock Manager" + }, + { + "role": "Stock User" + }, + { + "role": "Accounts User" + } + ], "source": "Warehouse wise Stock Value", "timeseries": 0, "type": "Bar", From d6001e5ef9b9fd05b3e534c25cc36f388f8e57ee Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 22:31:16 +0530 Subject: [PATCH 40/50] fix: stock entry not fetching expired batches (backport #44863) (#44868) fix: stock entry not fetching expired batches (#44863) (cherry picked from commit c9b143b509c18a31b65f252d495b69eb24ab4f53) Co-authored-by: rohitwaghchaure --- erpnext/controllers/stock_controller.py | 2 +- .../stock/doctype/stock_entry/stock_entry.js | 1 + .../stock/doctype/stock_entry/stock_entry.py | 46 +++++++++++++++---- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 34556f725d41..6e0137461993 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -156,7 +156,7 @@ def validate_serialized_batch(self): from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos is_material_issue = False - if self.doctype == "Stock Entry" and self.purpose == "Material Issue": + if self.doctype == "Stock Entry" and self.purpose in ["Material Issue", "Material Transfer"]: is_material_issue = True for d in self.get("items"): diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index 0e39c2a97565..df6a61d335bf 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -371,6 +371,7 @@ frappe.ui.form.on("Stock Entry", { function () { frappe.call({ method: "erpnext.stock.doctype.stock_entry.stock_entry.get_expired_batch_items", + freeze: true, callback: function (r) { if (!r.exc && r.message) { frm.set_value("items", []); diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index f362f9d3da9f..febc814b9787 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -2975,17 +2975,45 @@ def get_uom_details(item_code, uom, qty): @frappe.whitelist() def get_expired_batch_items(): - return frappe.db.sql( - """select b.item, sum(sle.actual_qty) as qty, sle.batch_no, sle.warehouse, sle.stock_uom\ - from `tabBatch` b, `tabStock Ledger Entry` sle - where b.expiry_date <= %s - and b.expiry_date is not NULL - and b.batch_id = sle.batch_no and sle.is_cancelled = 0 - group by sle.warehouse, sle.item_code, sle.batch_no""", - (nowdate()), - as_dict=1, + from erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle import get_auto_batch_nos + + expired_batches = get_expired_batches() + if not expired_batches: + return [] + + expired_batches_stock = get_auto_batch_nos( + frappe._dict( + { + "batch_no": list(expired_batches.keys()), + "for_stock_levels": True, + } + ) ) + for row in expired_batches_stock: + row.update(expired_batches.get(row.batch_no)) + + return expired_batches_stock + + +def get_expired_batches(): + batch = frappe.qb.DocType("Batch") + + data = ( + frappe.qb.from_(batch) + .select(batch.item, batch.name.as_("batch_no"), batch.stock_uom) + .where((batch.expiry_date <= nowdate()) & (batch.expiry_date.isnotnull())) + ).run(as_dict=True) + + if not data: + return [] + + expired_batches = frappe._dict() + for row in data: + expired_batches[row.batch_no] = row + + return expired_batches + @frappe.whitelist() def get_warehouse_details(args): From 516a325a31d48d5833b285e78cd5dd2f7e2f91c9 Mon Sep 17 00:00:00 2001 From: Khushi Rawat <142375893+khushi8112@users.noreply.github.com> Date: Mon, 23 Dec 2024 15:42:18 +0530 Subject: [PATCH 41/50] fix: asset field precision check (cherry picked from commit 92b8768ae2e6327b68e723113529f5ee529a18d6) --- erpnext/assets/doctype/asset/asset.py | 12 +++++------- .../asset_depreciation_schedule.py | 14 +++++++++----- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 243ad0090500..e499b5e0faaf 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -308,12 +308,14 @@ def validate_finance_books(self): ) def validate_precision(self): - float_precision = cint(frappe.db.get_default("float_precision")) or 2 if self.gross_purchase_amount: - self.gross_purchase_amount = flt(self.gross_purchase_amount, float_precision) + self.gross_purchase_amount = flt( + self.gross_purchase_amount, self.precision("gross_purchase_amount") + ) + if self.opening_accumulated_depreciation: self.opening_accumulated_depreciation = flt( - self.opening_accumulated_depreciation, float_precision + self.opening_accumulated_depreciation, self.precision("opening_accumulated_depreciation") ) def validate_asset_values(self): @@ -487,11 +489,7 @@ def set_total_booked_depreciations(self): def validate_expected_value_after_useful_life(self): for row in self.get("finance_books"): - row.expected_value_after_useful_life = flt( - row.expected_value_after_useful_life, self.precision("gross_purchase_amount") - ) depr_schedule = get_depr_schedule(self.name, "Draft", row.finance_book) - if not depr_schedule: continue diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 679fbfe2e58d..fe9fa870e0a7 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -430,6 +430,7 @@ def _make_depr_schedule( if not depreciation_amount: continue + depreciation_amount = flt(depreciation_amount, asset_doc.precision("gross_purchase_amount")) value_after_depreciation = flt( value_after_depreciation - flt(depreciation_amount), asset_doc.precision("gross_purchase_amount"), @@ -443,6 +444,7 @@ def _make_depr_schedule( depreciation_amount += flt(value_after_depreciation) - flt( row.expected_value_after_useful_life ) + depreciation_amount = flt(depreciation_amount, asset_doc.precision("gross_purchase_amount")) skip_row = True if flt(depreciation_amount, asset_doc.precision("gross_purchase_amount")) > 0: @@ -517,10 +519,13 @@ def set_accumulated_depreciation( i - 1 ].accumulated_depreciation_amount else: - accumulated_depreciation = flt(self.opening_accumulated_depreciation) + accumulated_depreciation = flt( + self.opening_accumulated_depreciation, + asset_doc.precision("opening_accumulated_depreciation"), + ) - depreciation_amount = flt(d.depreciation_amount, d.precision("depreciation_amount")) - value_after_depreciation -= flt(depreciation_amount) + value_after_depreciation -= flt(d.depreciation_amount) + value_after_depreciation = flt(value_after_depreciation, d.precision("depreciation_amount")) # for the last row, if depreciation method = Straight Line if ( @@ -530,12 +535,11 @@ def set_accumulated_depreciation( and not date_of_return and not row.shift_based ): - depreciation_amount += flt( + d.depreciation_amount += flt( value_after_depreciation - flt(row.expected_value_after_useful_life), d.precision("depreciation_amount"), ) - d.depreciation_amount = depreciation_amount accumulated_depreciation += d.depreciation_amount d.accumulated_depreciation_amount = flt( accumulated_depreciation, d.precision("accumulated_depreciation_amount") From ddfead2cde3a25c95bb1bff79680a41365ebf8de Mon Sep 17 00:00:00 2001 From: Khushi Rawat <142375893+khushi8112@users.noreply.github.com> Date: Mon, 23 Dec 2024 23:37:51 +0530 Subject: [PATCH 42/50] fix: test case correction (cherry picked from commit 2f7e6230a6c15885e291902c509e36a2017ec8b4) --- erpnext/assets/doctype/asset/test_asset.py | 2 +- .../asset_depreciation_schedule/asset_depreciation_schedule.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 06f170200a86..8a320d617ff5 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -889,7 +889,7 @@ def test_pro_rata_depreciation_entry_for_wdv(self): ["2030-12-31", 28630.14, 28630.14], ["2031-12-31", 35684.93, 64315.07], ["2032-12-31", 17842.46, 82157.53], - ["2033-06-06", 5342.46, 87499.99], + ["2033-06-06", 5342.47, 87500.00], ] schedules = [ diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index fe9fa870e0a7..a60478ac8a15 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -344,7 +344,7 @@ def _make_depr_schedule( date_of_disposal, original_schedule_date=schedule_date, ) - + depreciation_amount = flt(depreciation_amount, asset_doc.precision("gross_purchase_amount")) if depreciation_amount > 0: self.add_depr_schedule_row(date_of_disposal, depreciation_amount, n) From 7a5c30fe9b5e3833ffeba46cead6ba42a69c0add Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 24 Dec 2024 09:06:37 +0530 Subject: [PATCH 43/50] fix: posting_time issue (#44870) (cherry picked from commit 079b86044efce7bf04c94900cdde6b1119c53fb2) # Conflicts: # erpnext/stock/deprecated_serial_batch.py --- erpnext/stock/deprecated_serial_batch.py | 9 ++++++++- erpnext/stock/serial_batch_bundle.py | 5 ++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/deprecated_serial_batch.py b/erpnext/stock/deprecated_serial_batch.py index d10833b6d463..b2c3e75b5a03 100644 --- a/erpnext/stock/deprecated_serial_batch.py +++ b/erpnext/stock/deprecated_serial_batch.py @@ -3,8 +3,12 @@ import frappe from frappe.query_builder.functions import CombineDatetime, Sum +<<<<<<< HEAD from frappe.utils import flt from frappe.utils.deprecations import deprecated +======= +from frappe.utils import flt, nowtime +>>>>>>> 079b86044e (fix: posting_time issue (#44870)) from pypika import Order @@ -112,7 +116,10 @@ def get_sle_for_batches(self): sle = frappe.qb.DocType("Stock Ledger Entry") timestamp_condition = None - if self.sle.posting_date and self.sle.posting_time: + if self.sle.posting_date: + if self.sle.posting_time is None: + self.sle.posting_time = nowtime() + posting_datetime = get_combine_datetime(self.sle.posting_date, self.sle.posting_time) if not self.sle.creation: posting_datetime = posting_datetime + datetime.timedelta(milliseconds=1) diff --git a/erpnext/stock/serial_batch_bundle.py b/erpnext/stock/serial_batch_bundle.py index 732a14c2fb5b..c450bf1a086d 100644 --- a/erpnext/stock/serial_batch_bundle.py +++ b/erpnext/stock/serial_batch_bundle.py @@ -643,7 +643,10 @@ def get_batch_no_ledgers(self) -> list[dict]: child = frappe.qb.DocType("Serial and Batch Entry") timestamp_condition = "" - if self.sle.posting_date and self.sle.posting_time: + if self.sle.posting_date: + if self.sle.posting_time is None: + self.sle.posting_time = nowtime() + timestamp_condition = CombineDatetime(parent.posting_date, parent.posting_time) < CombineDatetime( self.sle.posting_date, self.sle.posting_time ) From 90aadcdcbc04734b3b47de70d263e541b874f4e2 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 24 Dec 2024 10:16:53 +0530 Subject: [PATCH 44/50] chore: fix conflicts --- erpnext/stock/deprecated_serial_batch.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/erpnext/stock/deprecated_serial_batch.py b/erpnext/stock/deprecated_serial_batch.py index b2c3e75b5a03..b3f4c2dead45 100644 --- a/erpnext/stock/deprecated_serial_batch.py +++ b/erpnext/stock/deprecated_serial_batch.py @@ -3,12 +3,8 @@ import frappe from frappe.query_builder.functions import CombineDatetime, Sum -<<<<<<< HEAD -from frappe.utils import flt -from frappe.utils.deprecations import deprecated -======= from frappe.utils import flt, nowtime ->>>>>>> 079b86044e (fix: posting_time issue (#44870)) +from frappe.utils.deprecations import deprecated from pypika import Order From ca7c229e863aefc8fcf9181513afa309b2c3fd25 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 24 Dec 2024 10:48:15 +0530 Subject: [PATCH 45/50] fix: Paid + Write Off Amount issue in Sales Invoice (backport #44763) (#44874) fix: Paid + Write Off Amount issue in Sales Invoice (cherry picked from commit 1fd7ba7c8879828526dedcce956b6bd59f10a4a9) Co-authored-by: vishakhdesai --- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 1a7ffc3c339b..dc2b44e7527a 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1002,9 +1002,9 @@ def validate_proj_cust(self): def validate_pos(self): if self.is_return: invoice_total = self.rounded_total or self.grand_total - if flt(self.paid_amount) + flt(self.write_off_amount) - flt(invoice_total) > 1.0 / ( - 10.0 ** (self.precision("grand_total") + 1.0) - ): + if abs(flt(self.paid_amount)) + abs(flt(self.write_off_amount)) - abs( + flt(invoice_total) + ) > 1.0 / (10.0 ** (self.precision("grand_total") + 1.0)): frappe.throw(_("Paid amount + Write Off Amount can not be greater than Grand Total")) def validate_warehouse(self): From 96cc9e29a190f9dffe47ee8b6e59e4353263aa89 Mon Sep 17 00:00:00 2001 From: Abdeali Chharchhodawala <99460106+Abdeali099@users.noreply.github.com> Date: Tue, 24 Dec 2024 10:22:32 +0530 Subject: [PATCH 46/50] fix: add `Stock UOM` when adding new item in POS list (#44780) --- erpnext/selling/page/point_of_sale/pos_controller.js | 12 ++++++++++-- .../selling/page/point_of_sale/pos_item_selector.js | 5 ++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js index c1127c39cc04..32cb2bc05250 100644 --- a/erpnext/selling/page/point_of_sale/pos_controller.js +++ b/erpnext/selling/page/point_of_sale/pos_controller.js @@ -574,11 +574,19 @@ erpnext.PointOfSale.Controller = class { } else { if (!this.frm.doc.customer) return this.raise_customer_selection_alert(); - const { item_code, batch_no, serial_no, rate, uom } = item; + const { item_code, batch_no, serial_no, rate, uom, stock_uom } = item; if (!item_code) return; - const new_item = { item_code, batch_no, rate, uom, [field]: value }; + if (rate == undefined || rate == 0) { + frappe.show_alert({ + message: __("Price is not set for the item."), + indicator: "orange", + }); + frappe.utils.play_sound("error"); + return; + } + const new_item = { item_code, batch_no, rate, uom, [field]: value, stock_uom }; if (serial_no) { await this.check_serial_no_availablilty(item_code, this.frm.doc.set_warehouse, serial_no); diff --git a/erpnext/selling/page/point_of_sale/pos_item_selector.js b/erpnext/selling/page/point_of_sale/pos_item_selector.js index 207a444218ba..9882c2d201ef 100644 --- a/erpnext/selling/page/point_of_sale/pos_item_selector.js +++ b/erpnext/selling/page/point_of_sale/pos_item_selector.js @@ -118,6 +118,7 @@ erpnext.PointOfSale.ItemSelector = class { data-item-code="${escape(item.item_code)}" data-serial-no="${escape(serial_no)}" data-batch-no="${escape(batch_no)}" data-uom="${escape(uom)}" data-rate="${escape(price_list_rate || 0)}" + data-stock-uom="${escape(item.stock_uom)}" title="${item.item_name}"> ${get_item_image_html()} @@ -251,17 +252,19 @@ erpnext.PointOfSale.ItemSelector = class { let serial_no = unescape($item.attr("data-serial-no")); let uom = unescape($item.attr("data-uom")); let rate = unescape($item.attr("data-rate")); + let stock_uom = unescape($item.attr("data-stock-uom")); // escape(undefined) returns "undefined" then unescape returns "undefined" batch_no = batch_no === "undefined" ? undefined : batch_no; serial_no = serial_no === "undefined" ? undefined : serial_no; uom = uom === "undefined" ? undefined : uom; rate = rate === "undefined" ? undefined : rate; + stock_uom = stock_uom === "undefined" ? undefined : stock_uom; me.events.item_selected({ field: "qty", value: "+1", - item: { item_code, batch_no, serial_no, uom, rate }, + item: { item_code, batch_no, serial_no, uom, rate, stock_uom }, }); me.search_field.set_focus(); }); From 5ca60f3e0a353fe18e1db9275bc683852842d6f3 Mon Sep 17 00:00:00 2001 From: ljain112 Date: Thu, 19 Dec 2024 16:27:04 +0530 Subject: [PATCH 47/50] fix: correct tds rate with lower deduction certificate (cherry picked from commit cb9c12d4952f68cf4a175fdd3adc470f37e40272) --- .../tax_withholding_category/tax_withholding_category.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py index 9a690a261228..cde1d24e5b4f 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py +++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py @@ -247,14 +247,14 @@ def get_tax_row_for_tds(tax_details, tax_amount): } -def get_lower_deduction_certificate(company, tax_details, pan_no): +def get_lower_deduction_certificate(company, posting_date, tax_details, pan_no): ldc_name = frappe.db.get_value( "Lower Deduction Certificate", { "pan_no": pan_no, "tax_withholding_category": tax_details.tax_withholding_category, - "valid_from": (">=", tax_details.from_date), - "valid_upto": ("<=", tax_details.to_date), + "valid_from": ("<=", posting_date), + "valid_upto": (">=", posting_date), "company": company, }, "name", @@ -302,7 +302,7 @@ def get_tax_amount(party_type, parties, inv, tax_details, posting_date, pan_no=N tax_amount = 0 if party_type == "Supplier": - ldc = get_lower_deduction_certificate(inv.company, tax_details, pan_no) + ldc = get_lower_deduction_certificate(inv.company, posting_date, tax_details, pan_no) if tax_deducted: net_total = inv.tax_withholding_net_total if ldc: From 57e6ed464594eb096c3a5956874b4773fc3abe97 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 24 Dec 2024 15:12:32 +0530 Subject: [PATCH 48/50] fix: set project in GL from the SLE (backport #44879) (#44885) fix: set project in GL from the SLE (#44879) (cherry picked from commit 021d077808a200be4cda178ac0df0b9bcce4886c) Co-authored-by: rohitwaghchaure --- erpnext/controllers/stock_controller.py | 45 ++++++++++++++++--------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 6e0137461993..970dc348057a 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -530,7 +530,7 @@ def get_gl_entries(self, warehouse_account=None, default_expense_account=None, d "account": warehouse_account[sle.warehouse]["account"], "against": expense_account, "cost_center": item_row.cost_center, - "project": item_row.project or self.get("project"), + "project": sle.get("project") or item_row.project or self.get("project"), "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "debit": flt(sle.stock_value_difference, precision), "is_opening": item_row.get("is_opening") @@ -550,7 +550,9 @@ def get_gl_entries(self, warehouse_account=None, default_expense_account=None, d "cost_center": item_row.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "debit": -1 * flt(sle.stock_value_difference, precision), - "project": item_row.get("project") or self.get("project"), + "project": sle.get("project") + or item_row.get("project") + or self.get("project"), "is_opening": item_row.get("is_opening") or self.get("is_opening") or "No", @@ -678,23 +680,34 @@ def get_items_and_warehouses(self) -> tuple[list[str], list[str]]: def get_stock_ledger_details(self): stock_ledger = {} - stock_ledger_entries = frappe.db.sql( - """ - select - name, warehouse, stock_value_difference, valuation_rate, - voucher_detail_no, item_code, posting_date, posting_time, - actual_qty, qty_after_transaction - from - `tabStock Ledger Entry` - where - voucher_type=%s and voucher_no=%s and is_cancelled = 0 - """, - (self.doctype, self.name), - as_dict=True, - ) + + table = frappe.qb.DocType("Stock Ledger Entry") + + stock_ledger_entries = ( + frappe.qb.from_(table) + .select( + table.name, + table.warehouse, + table.stock_value_difference, + table.valuation_rate, + table.voucher_detail_no, + table.item_code, + table.posting_date, + table.posting_time, + table.actual_qty, + table.qty_after_transaction, + table.project, + ) + .where( + (table.voucher_type == self.doctype) + & (table.voucher_no == self.name) + & (table.is_cancelled == 0) + ) + ).run(as_dict=True) for sle in stock_ledger_entries: stock_ledger.setdefault(sle.voucher_detail_no, []).append(sle) + return stock_ledger def check_expense_account(self, item): From 69ed2a9dfe905e9d655e3f94ff608457ad09623f Mon Sep 17 00:00:00 2001 From: venkat102 Date: Tue, 24 Dec 2024 15:34:39 +0530 Subject: [PATCH 49/50] refactor: use db_set instead of set_value to trigger notification (cherry picked from commit f8b923edfee32ad1a7d306c9e5445e9aed2702d9) --- erpnext/accounts/doctype/bank_clearance/bank_clearance.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py index ac7883fce138..7f08653b15b4 100644 --- a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py +++ b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py @@ -117,9 +117,9 @@ def update_clearance_date(self): ) else: - frappe.db.set_value( - d.payment_document, d.payment_entry, "clearance_date", d.clearance_date - ) + # using db_set to trigger notification + payment_entry = frappe.get_doc(d.payment_document, d.payment_entry) + payment_entry.db_set("clearance_date", d.clearance_date) clearance_date_updated = True From 771632a5e2be9ac2981d951481267ea2244094dd Mon Sep 17 00:00:00 2001 From: venkat102 Date: Tue, 24 Dec 2024 12:35:38 +0530 Subject: [PATCH 50/50] fix: show profit and loss after period closing (cherry picked from commit dc5cd93bf0448eea9c2caef77413aa18058c3243) --- .../consolidated_financial_statement.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py index d287b30bf0be..04625fc76fcd 100644 --- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py +++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py @@ -350,7 +350,7 @@ def get_data(companies, root_type, balance_must_be, fiscal_year, filters=None, i gl_entries_by_account, accounts_by_name, accounts, - ignore_closing_entries=False, + ignore_closing_entries=ignore_closing_entries, root_type=root_type, )