def voucher_to_invoice(voucher): if voucher.VOUCHERTYPENAME.string.strip() in ["Sales", "Credit Note"]: doctype = "Sales Invoice" party_field = "customer" account_field = "debit_to" account_name = encode_company_abbr(self.tally_debtors_account, self.erpnext_company) price_list_field = "selling_price_list" elif voucher.VOUCHERTYPENAME.string.strip() in ["Purchase", "Debit Note"]: doctype = "Purchase Invoice" party_field = "supplier" account_field = "credit_to" account_name = encode_company_abbr(self.tally_creditors_account, self.erpnext_company) price_list_field = "buying_price_list" else: # Do not handle vouchers other than "Purchase", "Debit Note", "Sales" and "Credit Note" # Do not handle Custom Vouchers either return invoice = { "doctype": doctype, party_field: voucher.PARTYNAME.string.strip(), "tally_guid": voucher.GUID.string.strip(), "tally_voucher_no": voucher.VOUCHERNUMBER.string.strip() if voucher.VOUCHERNUMBER else "", "posting_date": voucher.DATE.string.strip(), "due_date": voucher.DATE.string.strip(), "items": get_voucher_items(voucher, doctype), "taxes": get_voucher_taxes(voucher), account_field: account_name, price_list_field: "Tally Price List", "set_posting_time": 1, "disable_rounded_total": 1, "company": self.erpnext_company, } return invoice
def _import_day_book_data(self): def create_fiscal_years(vouchers): from frappe.utils.data import add_years, getdate earliest_date = getdate(min(voucher["posting_date"] for voucher in vouchers)) oldest_year = frappe.get_all("Fiscal Year", fields=["year_start_date", "year_end_date"], order_by="year_start_date")[0] while earliest_date < oldest_year.year_start_date: new_year = frappe.get_doc({"doctype": "Fiscal Year"}) new_year.year_start_date = add_years(oldest_year.year_start_date, -1) new_year.year_end_date = add_years(oldest_year.year_end_date, -1) if new_year.year_start_date.year == new_year.year_end_date.year: new_year.year = new_year.year_start_date.year else: new_year.year = "{}-{}".format(new_year.year_start_date.year, new_year.year_end_date.year) new_year.save() oldest_year = new_year def create_custom_fields(doctypes): for doctype in doctypes: df = { "fieldtype": "Data", "fieldname": "tally_guid", "read_only": 1, "label": "Tally GUID" } create_custom_field(doctype, df) def create_price_list(): frappe.get_doc({ "doctype": "Price List", "price_list_name": "Tally Price List", "selling": 1, "buying": 1, "enabled": 1, "currency": "INR" }).insert() frappe.db.set_value("Account", encode_company_abbr(self.tally_creditors_account, self.erpnext_company), "account_type", "Payable") frappe.db.set_value("Account", encode_company_abbr(self.tally_debtors_account, self.erpnext_company), "account_type", "Receivable") frappe.db.set_value("Company", self.erpnext_company, "round_off_account", self.round_off_account) vouchers_file = frappe.get_doc("File", {"file_url": self.vouchers}) vouchers = json.loads(vouchers_file.get_content()) create_fiscal_years(vouchers) create_price_list() create_custom_fields(["Journal Entry", "Purchase Invoice", "Sales Invoice"]) total = len(vouchers) is_last = False for index in range(0, total, VOUCHER_CHUNK_SIZE): if index + VOUCHER_CHUNK_SIZE >= total: is_last = True frappe.enqueue_doc(self.doctype, self.name, "_import_vouchers", queue="long", timeout=3600, start=index+1, total=total, is_last=is_last)
def get_party(party): if frappe.db.exists({ "doctype": "Supplier", "supplier_name": party }): return "Supplier", encode_company_abbr( self.tally_creditors_account, self.erpnext_company) elif frappe.db.exists({ "doctype": "Customer", "customer_name": party }): return "Customer", encode_company_abbr( self.tally_debtors_account, self.erpnext_company)
def test_encode_company_abbr(self): abbr = "NFECT" names = [ "Warehouse Name", "ERPNext Foundation India", "Gold - Member - {a}".format(a=abbr), " - {a}".format(a=abbr), "ERPNext - Foundation - India", "ERPNext Foundation India - {a}".format(a=abbr), "No-Space-{a}".format(a=abbr), "- Warehouse", ] expected_names = [ "Warehouse Name - {a}".format(a=abbr), "ERPNext Foundation India - {a}".format(a=abbr), "Gold - Member - {a}".format(a=abbr), " - {a}".format(a=abbr), "ERPNext - Foundation - India - {a}".format(a=abbr), "ERPNext Foundation India - {a}".format(a=abbr), "No-Space-{a} - {a}".format(a=abbr), "- Warehouse - {a}".format(a=abbr), ] for i in range(len(names)): enc_name = encode_company_abbr(names[i], abbr=abbr) self.assertTrue( enc_name == expected_names[i], "{enc} is not same as {exp}".format(enc=enc_name, exp=expected_names[i]), )
def test_encode_company_abbr(self): company = frappe.new_doc("Company") company.company_name = "New from Existing Company For Test" company.abbr = "NFECT" company.default_currency = "INR" company.save() abbr = company.abbr names = [ "Warehouse Name", "ERPNext Foundation India", "Gold - Member - {a}".format(a=abbr), " - {a}".format(a=abbr), "ERPNext - Foundation - India", "ERPNext Foundation India - {a}".format(a=abbr), "No-Space-{a}".format(a=abbr), "- Warehouse" ] expected_names = [ "Warehouse Name - {a}".format(a=abbr), "ERPNext Foundation India - {a}".format(a=abbr), "Gold - Member - {a}".format(a=abbr), " - {a}".format(a=abbr), "ERPNext - Foundation - India - {a}".format(a=abbr), "ERPNext Foundation India - {a}".format(a=abbr), "No-Space-{a} - {a}".format(a=abbr), "- Warehouse - {a}".format(a=abbr) ] for i in range(len(names)): enc_name = encode_company_abbr(names[i], company.name) self.assertTrue( enc_name == expected_names[i], "{enc} is not same as {exp}".format(enc=enc_name, exp=expected_names[i]) )
def test_encode_company_abbr(self): company = frappe.new_doc("Company") company.company_name = "New from Existing Company For Test" company.abbr = "NFECT" company.default_currency = "INR" company.save() abbr = company.abbr names = [ "Warehouse Name", "ERPNext Foundation India", "Gold - Member - {a}".format(a=abbr), " - {a}".format(a=abbr), "ERPNext - Foundation - India", "ERPNext Foundation India - {a}".format(a=abbr), "No-Space-{a}".format(a=abbr), "- Warehouse" ] expected_names = [ "Warehouse Name - {a}".format(a=abbr), "ERPNext Foundation India - {a}".format(a=abbr), "Gold - Member - {a}".format(a=abbr), " - {a}".format(a=abbr), "ERPNext - Foundation - India - {a}".format(a=abbr), "ERPNext Foundation India - {a}".format(a=abbr), "No-Space-{a} - {a}".format(a=abbr), "- Warehouse - {a}".format(a=abbr) ] for i in range(len(names)): enc_name = encode_company_abbr(names[i], company.name) self.assertTrue( enc_name == expected_names[i], "{enc} is not same as {exp}".format(enc=enc_name, exp=expected_names[i]))
def voucher_to_journal_entry(voucher): accounts = [] ledger_entries = voucher.find_all("ALLLEDGERENTRIES.LIST") + voucher.find_all( "LEDGERENTRIES.LIST" ) for entry in ledger_entries: account = { "account": encode_company_abbr(entry.LEDGERNAME.string.strip(), self.erpnext_company), "cost_center": self.default_cost_center, } if entry.ISPARTYLEDGER.string.strip() == "Yes": party_details = get_party(entry.LEDGERNAME.string.strip()) if party_details: party_type, party_account = party_details account["party_type"] = party_type account["account"] = party_account account["party"] = entry.LEDGERNAME.string.strip() amount = Decimal(entry.AMOUNT.string.strip()) if amount > 0: account["credit_in_account_currency"] = str(abs(amount)) else: account["debit_in_account_currency"] = str(abs(amount)) accounts.append(account) journal_entry = { "doctype": "Journal Entry", "tally_guid": voucher.GUID.string.strip(), "tally_voucher_no": voucher.VOUCHERNUMBER.string.strip() if voucher.VOUCHERNUMBER else "", "posting_date": voucher.DATE.string.strip(), "company": self.erpnext_company, "accounts": accounts, } return journal_entry
def _save_customer(self, customer): try: if not frappe.db.exists({"doctype": "Customer", "quickbooks_id": customer["Id"], "company": self.company}): try: receivable_account = frappe.get_all("Account", filters={ "account_type": "Receivable", "account_currency": customer["CurrencyRef"]["value"], "company": self.company, })[0]["name"] except Exception: receivable_account = None erpcustomer = frappe.get_doc({ "doctype": "Customer", "quickbooks_id": customer["Id"], "customer_name": encode_company_abbr(customer["DisplayName"], self.company), "customer_type": "Individual", "customer_group": "Commercial", "default_currency": customer["CurrencyRef"]["value"], "accounts": [{"company": self.company, "account": receivable_account}], "territory": "All Territories", "company": self.company, }).insert() if "BillAddr" in customer: self._create_address(erpcustomer, "Customer", customer["BillAddr"], "Billing") if "ShipAddr" in customer: self._create_address(erpcustomer, "Customer", customer["ShipAddr"], "Shipping") except Exception as e: self._log_error(e, customer)
def get_voucher_items(voucher, doctype): inventory_entries = ( voucher.find_all("INVENTORYENTRIES.LIST") + voucher.find_all("ALLINVENTORYENTRIES.LIST") + voucher.find_all("INVENTORYENTRIESIN.LIST") + voucher.find_all("INVENTORYENTRIESOUT.LIST") ) if doctype == "Sales Invoice": account_field = "income_account" elif doctype == "Purchase Invoice": account_field = "expense_account" items = [] for entry in inventory_entries: qty, uom = entry.ACTUALQTY.string.strip().split() items.append( { "item_code": entry.STOCKITEMNAME.string.strip(), "description": entry.STOCKITEMNAME.string.strip(), "qty": qty.strip(), "uom": uom.strip(), "conversion_factor": 1, "price_list_rate": entry.RATE.string.strip().split("/")[0], "cost_center": self.default_cost_center, "warehouse": self.default_warehouse, account_field: encode_company_abbr( entry.find_all("ACCOUNTINGALLOCATIONS.LIST")[0].LEDGERNAME.string.strip(), self.erpnext_company, ), } ) return items
def _save_customer(self, customer): try: if not frappe.db.exists({"doctype": "Customer", "quickbooks_id": customer["Id"], "company": self.company}): try: receivable_account = frappe.get_all("Account", filters={ "account_type": "Receivable", "account_currency": customer["CurrencyRef"]["value"], "company": self.company, })[0]["name"] except Exception as e: receivable_account = None erpcustomer = frappe.get_doc({ "doctype": "Customer", "quickbooks_id": customer["Id"], "customer_name" : encode_company_abbr(customer["DisplayName"], self.company), "customer_type" : "Individual", "customer_group" : "Commercial", "default_currency": customer["CurrencyRef"]["value"], "accounts": [{"company": self.company, "account": receivable_account}], "territory" : "All Territories", "company": self.company, }).insert() if "BillAddr" in customer: self._create_address(erpcustomer, "Customer", customer["BillAddr"], "Billing") if "ShipAddr" in customer: self._create_address(erpcustomer, "Customer", customer["ShipAddr"], "Shipping") except Exception as e: self._log_error(e, customer)
def _get_unique_account_name(self, quickbooks_name, number=0): if number: quickbooks_account_name = "{} - {} - QB".format(quickbooks_name, number) else: quickbooks_account_name = "{} - QB".format(quickbooks_name) company_encoded_account_name = encode_company_abbr(quickbooks_account_name, self.company) if frappe.db.exists({"doctype": "Account", "name": company_encoded_account_name, "company": self.company}): unique_account_name = self._get_unique_account_name(quickbooks_name, number + 1) else: unique_account_name = quickbooks_account_name return unique_account_name
def before_rename(self, old_name, new_name, merge=False): # Add company abbr if not provided new_warehouse = erpnext.encode_company_abbr(new_name, self.company) if merge: if not frappe.db.exists("Warehouse", new_warehouse): frappe.throw(_("Warehouse {0} does not exist").format(new_warehouse)) if self.company != frappe.db.get_value("Warehouse", new_warehouse, "company"): frappe.throw(_("Both Warehouse must belong to same Company")) return new_warehouse
def _save_tax_rate(self, tax_rate): try: if not frappe.db.exists({"doctype": "Account", "quickbooks_id": "TaxRate - {}".format(tax_rate["Id"]), "company": self.company}): frappe.get_doc({ "doctype": "Account", "quickbooks_id": "TaxRate - {}".format(tax_rate["Id"]), "account_name": "{} - QB".format(tax_rate["Name"]), "root_type": "Liability", "parent_account": encode_company_abbr("{} - QB".format("Liability"), self.company), "is_group": "0", "company": self.company, }).insert() except Exception as e: self._log_error(e, tax_rate)
def get_voucher_taxes(voucher): ledger_entries = voucher.find_all("ALLLEDGERENTRIES.LIST") + voucher.find_all("LEDGERENTRIES.LIST") taxes = [] for entry in ledger_entries: if entry.ISPARTYLEDGER.string == "No": tax_account = encode_company_abbr(entry.LEDGERNAME.string, self.erpnext_company) taxes.append({ "charge_type": "Actual", "account_head": tax_account, "description": tax_account, "tax_amount": entry.AMOUNT.string, "cost_center": self.default_cost_center, }) return taxes
def before_rename(self, old_name, new_name, merge=False): super(Warehouse, self).before_rename(old_name, new_name, merge) # Add company abbr if not provided new_warehouse = erpnext.encode_company_abbr(new_name, self.company) if merge: if not frappe.db.exists("Warehouse", new_warehouse): frappe.throw(_("Warehouse {0} does not exist").format(new_warehouse)) if self.company != frappe.db.get_value("Warehouse", new_warehouse, "company"): frappe.throw(_("Both Warehouse must belong to same Company")) return new_warehouse
def _make_root_accounts(self): roots = ["Asset", "Equity", "Expense", "Liability", "Income"] for root in roots: try: if not frappe.db.exists({"doctype": "Account", "name": encode_company_abbr("{} - QB".format(root), self.company), "company": self.company}): frappe.get_doc({ "doctype": "Account", "account_name": "{} - QB".format(root), "root_type": root, "is_group": "1", "company": self.company, }).insert(ignore_mandatory=True) except Exception as e: self._log_error(e, root) frappe.db.commit()
def before_rename(self, old_name, new_name, merge=False): # Add company abbr if not provided new_Headquarter = erpnext.encode_company_abbr(new_name, self.company) if merge: if not frappe.db.exists("Headquarter", new_Headquarter): frappe.throw( _("Headquarter {0} does not exist").format( new_Headquarter)) if self.company != frappe.db.get_value("Headquarter", new_Headquarter, "company"): frappe.throw(_("Both Headquarter must belong to same Company")) return new_Headquarter
def _save_vendor(self, vendor): try: if not frappe.db.exists({"doctype": "Supplier", "quickbooks_id": vendor["Id"], "company": self.company}): erpsupplier = frappe.get_doc({ "doctype": "Supplier", "quickbooks_id": vendor["Id"], "supplier_name" : encode_company_abbr(vendor["DisplayName"], self.company), "supplier_group" : "All Supplier Groups", "company": self.company, }).insert() if "BillAddr" in vendor: self._create_address(erpsupplier, "Supplier", vendor["BillAddr"], "Billing") if "ShipAddr" in vendor: self._create_address(erpsupplier, "Supplier",vendor["ShipAddr"], "Shipping") except Exception as e: self._log_error(e)
def _save_vendor(self, vendor): try: if not frappe.db.exists({"doctype": "Supplier", "quickbooks_id": vendor["Id"], "company": self.company}): erpsupplier = frappe.get_doc({ "doctype": "Supplier", "quickbooks_id": vendor["Id"], "supplier_name": encode_company_abbr(vendor["DisplayName"], self.company), "supplier_group": "All Supplier Groups", "company": self.company, }).insert() if "BillAddr" in vendor: self._create_address(erpsupplier, "Supplier", vendor["BillAddr"], "Billing") if "ShipAddr" in vendor: self._create_address(erpsupplier, "Supplier", vendor["ShipAddr"], "Shipping") except Exception as e: self._log_error(e)
def create_warehouse(warehouse_name, properties=None, company=None): if not company: company = "_Test Company" warehouse_id = erpnext.encode_company_abbr(warehouse_name, company) if not frappe.db.exists("Warehouse", warehouse_id): warehouse = frappe.new_doc("Warehouse") warehouse.warehouse_name = warehouse_name warehouse.parent_warehouse = "All Warehouses - _TCUV" warehouse.company = company warehouse.account = get_warehouse_account(warehouse_name, company) if properties: warehouse.update(properties) warehouse.save() return warehouse.name else: return warehouse_id
def create_warehouse(warehouse_name, properties=None, company=None): if not company: company = "_Test Company" warehouse_id = erpnext.encode_company_abbr(warehouse_name, company) if not frappe.db.exists("Warehouse", warehouse_id): w = frappe.new_doc("Warehouse") w.warehouse_name = warehouse_name w.parent_warehouse = "_Test Warehouse Group - _TC" w.company = company make_account_for_warehouse(warehouse_name, w) w.account = warehouse_id if properties: w.update(properties) w.save() return w.name else: return warehouse_id
def rename_account_for(self, old_name, new_name, merge): old_account_name = frappe.get_value('Account', dict(warehouse=old_name)) if old_account_name: if not merge: # old account name is same as old name, so rename the account too if old_account_name == erpnext.encode_company_abbr(old_name, self.company): frappe.rename_doc("Account", old_account_name, new_name) else: # merge target_account = frappe.get_value('Account', dict(warehouse=new_name)) if target_account: # target warehouse has account, merge into target account frappe.rename_doc("Account", old_account_name, target_account, merge=True) else: # target warehouse does not have account, use this account frappe.rename_doc("Account", old_account_name, new_name, merge=False) # rename link frappe.db.set_value('Account', new_name, 'warehouse', new_name)
def _save_item(self, item): try: if not frappe.db.exists({"doctype": "Item", "quickbooks_id": item["Id"], "company": self.company}): if item["Type"] in ("Service", "Inventory"): item_dict = { "doctype": "Item", "quickbooks_id": item["Id"], "item_code": encode_company_abbr(item["Name"], self.company), "stock_uom": "Unit", "is_stock_item": 0, "item_group": "All Item Groups", "company": self.company, "item_defaults": [{"company": self.company, "default_warehouse": self.default_warehouse}] } if "ExpenseAccountRef" in item: expense_account = self._get_account_name_by_id(item["ExpenseAccountRef"]["value"]) item_dict["item_defaults"][0]["expense_account"] = expense_account if "IncomeAccountRef" in item: income_account = self._get_account_name_by_id(item["IncomeAccountRef"]["value"]) item_dict["item_defaults"][0]["income_account"] = income_account frappe.get_doc(item_dict).insert() except Exception as e: self._log_error(e, item)
def _save_item(self, item): try: if not frappe.db.exists({"doctype": "Item", "quickbooks_id": item["Id"], "company": self.company}): if item["Type"] in ("Service", "Inventory"): item_dict = { "doctype": "Item", "quickbooks_id": item["Id"], "item_code" : encode_company_abbr(item["Name"], self.company), "stock_uom": "Unit", "is_stock_item": 0, "item_group": "All Item Groups", "company": self.company, "item_defaults": [{"company": self.company, "default_warehouse": self.default_warehouse}] } if "ExpenseAccountRef" in item: expense_account = self._get_account_name_by_id(item["ExpenseAccountRef"]["value"]) item_dict["item_defaults"][0]["expense_account"] = expense_account if "IncomeAccountRef" in item: income_account = self._get_account_name_by_id(item["IncomeAccountRef"]["value"]) item_dict["item_defaults"][0]["income_account"] = income_account frappe.get_doc(item_dict).insert() except Exception as e: self._log_error(e, item)
def _save_account(self, account): mapping = { "Bank": "Asset", "Other Current Asset": "Asset", "Fixed Asset": "Asset", "Other Asset": "Asset", "Accounts Receivable": "Asset", "Equity": "Equity", "Expense": "Expense", "Other Expense": "Expense", "Cost of Goods Sold": "Expense", "Accounts Payable": "Liability", "Credit Card": "Liability", "Long Term Liability": "Liability", "Other Current Liability": "Liability", "Income": "Income", "Other Income": "Income", } # Map Quickbooks Account Types to ERPNext root_accunts and and root_type try: if not frappe.db.exists({"doctype": "Account", "quickbooks_id": account["Id"], "company": self.company}): is_child = account["SubAccount"] is_group = account["is_group"] # Create Two Accounts for every Group Account if is_group: account_id = "Group - {}".format(account["Id"]) else: account_id = account["Id"] if is_child: parent_account = self._get_account_name_by_id("Group - {}".format(account["ParentRef"]["value"])) else: parent_account = encode_company_abbr("{} - QB".format(mapping[account["AccountType"]]), self.company) frappe.get_doc({ "doctype": "Account", "quickbooks_id": account_id, "account_name": self._get_unique_account_name(account["Name"]), "root_type": mapping[account["AccountType"]], "account_type": self._get_account_type(account), "account_currency": account["CurrencyRef"]["value"], "parent_account": parent_account, "is_group": is_group, "company": self.company, }).insert() if is_group: # Create a Leaf account corresponding to the group account frappe.get_doc({ "doctype": "Account", "quickbooks_id": account["Id"], "account_name": self._get_unique_account_name(account["Name"]), "root_type": mapping[account["AccountType"]], "account_type": self._get_account_type(account), "account_currency": account["CurrencyRef"]["value"], "parent_account": self._get_account_name_by_id(account_id), "is_group": 0, "company": self.company, }).insert() if account.get("AccountSubType") == "UndepositedFunds": self.undeposited_funds_account = self._get_account_name_by_id(account["Id"]) self.save() except Exception as e: self._log_error(e, account)