Merge branch 'develop' into capacity_planning_for_workstataion_feature

This commit is contained in:
rohitwaghchaure 2019-12-02 11:29:06 +05:30 committed by GitHub
commit ce32f9a361
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
74 changed files with 2136 additions and 2677 deletions

View File

@ -1,465 +1,466 @@
{ {
"country_code": "ae", "country_code": "ae",
"name": "U.A.E - Chart of Accounts", "name": "U.A.E - Chart of Accounts",
"tree": { "tree": {
"Assets": { "Assets": {
"Current Assets": { "Current Assets": {
"Accounts Receivable": { "Accounts Receivable": {
"Corporate Credit Cards": { "Corporate Credit Cards": {
"account_type": "Receivable" "account_type": "Receivable"
}, },
"Other Receivable": { "Other Receivable": {
"Accrued Rebates Due from Suppliers": { "Accrued Rebates Due from Suppliers": {
"account_type": "Receivable" "account_type": "Receivable"
}, },
"Accrued Income from Suppliers": { "Accrued Income from Suppliers": {
"account_type": "Receivable" "account_type": "Receivable"
}, },
"Other Debtors": { "Other Debtors": {
"account_type": "Receivable" "account_type": "Receivable"
}, },
"account_type": "Receivable" "account_type": "Receivable"
}, },
"Post Dated Cheques Received": { "Post Dated Cheques Received": {
"account_type": "Receivable" "account_type": "Receivable"
}, },
"Staff Receivable": { "Staff Receivable": {
"account_type": "Receivable" "account_type": "Receivable"
}, },
"Trade Receivable": { "Trade Receivable": {
"account_type": "Receivable" "account_type": "Receivable"
}, },
"Trade in Opening Fees": { "Trade in Opening Fees": {
"account_type": "Receivable" "account_type": "Receivable"
}, },
"account_type": "Receivable" "account_type": "Receivable"
}, },
"Cash in Hand & Banks": { "Cash in Hand & Banks": {
"Banks": { "Banks": {
"Bank Margin On LC & LG": {}, "Bank Margin On LC & LG": {},
"Banks Blocked Deposits": {}, "Banks Blocked Deposits": {},
"Banks Call Deposit Accounts": {}, "Banks Call Deposit Accounts": {},
"Banks Current Accounts": { "Banks Current Accounts": {
"account_type": "Bank" "account_type": "Bank"
}, },
"account_type": "Bank" "account_type": "Bank"
}, },
"Cash in Hand": { "Cash in Hand": {
"Cash in Safe": { "Cash in Safe": {
"Main Safe": { "Main Safe": {
"account_type": "Cash" "account_type": "Cash"
}, },
"Main Safe - Foreign Currency": { "Main Safe - Foreign Currency": {
"account_type": "Cash" "account_type": "Cash"
} }
}, },
"Petty Cash": { "Petty Cash": {
"Petty Cash - Administration": { "Petty Cash - Administration": {
"account_type": "Cash" "account_type": "Cash"
}, },
"Petty Cash - Others": { "Petty Cash - Others": {
"account_type": "Cash" "account_type": "Cash"
} }
}, },
"account_type": "Cash" "account_type": "Cash"
}, },
"Cash in Transit": { "Cash in Transit": {
"Credit Cards": { "Credit Cards": {
"Gateway Credit Cards": { "Gateway Credit Cards": {
"account_type": "Bank" "account_type": "Bank"
}, },
"Manual Visa & Master Cards": { "Manual Visa & Master Cards": {
"account_type": "Bank" "account_type": "Bank"
}, },
"PayPal Account": { "PayPal Account": {
"account_type": "Bank" "account_type": "Bank"
}, },
"Visa & Master Credit Cards": { "Visa & Master Credit Cards": {
"account_type": "Bank" "account_type": "Bank"
} }
} }
} }
}, },
"Inventory": { "Inventory": {
"Consigned Stock": { "Consigned Stock": {
"Handling Difference in Inventory": { "Handling Difference in Inventory": {},
"account_type": "Stock Adjustment"
},
"Items Delivered to Customs on temporary Base": {} "Items Delivered to Customs on temporary Base": {}
}, },
"Stock in Hand": { "Stock in Hand": {
"account_type": "Stock" "account_type": "Stock"
} }
}, },
"Preliminary and Preoperating Expenses": { "Preliminary and Preoperating Expenses": {
"Preoperating Expenses": {} "Preoperating Expenses": {}
}, },
"Prepayments & Deposits": { "Prepayments & Deposits": {
"Deposits": { "Deposits": {
"Deposit - Office Rent": {}, "Deposit - Office Rent": {},
"Deposit Others": {}, "Deposit Others": {},
"Deposit to Immigration (Visa)": {}, "Deposit to Immigration (Visa)": {},
"Deposits - Customs": {} "Deposits - Customs": {}
}, },
"Prepaid Taxes": { "Prepaid Taxes": {
"Sales Taxes Receivables": {}, "Sales Taxes Receivables": {},
"Withholding Tax Receivables": {} "Withholding Tax Receivables": {}
}, },
"Prepayments": { "Prepayments": {
"Other Prepayments": {}, "Other Prepayments": {},
"PrePaid Advertisement Expenses": {}, "PrePaid Advertisement Expenses": {},
"Prepaid Bank Guarantee": {}, "Prepaid Bank Guarantee": {},
"Prepaid Consultancy Fees": {}, "Prepaid Consultancy Fees": {},
"Prepaid Employees Housing": {}, "Prepaid Employees Housing": {},
"Prepaid Finance charge for Loans": {}, "Prepaid Finance charge for Loans": {},
"Prepaid Legal Fees": {}, "Prepaid Legal Fees": {},
"Prepaid License Fees": {}, "Prepaid License Fees": {},
"Prepaid Life Insurance": {}, "Prepaid Life Insurance": {},
"Prepaid Maintenance": {}, "Prepaid Maintenance": {},
"Prepaid Medical Insurance": {}, "Prepaid Medical Insurance": {},
"Prepaid Office Rent": {}, "Prepaid Office Rent": {},
"Prepaid Other Insurance": {}, "Prepaid Other Insurance": {},
"Prepaid Schooling Fees": {}, "Prepaid Schooling Fees": {},
"Prepaid Site Hosting Fees": {}, "Prepaid Site Hosting Fees": {},
"Prepaid Sponsorship Fees": {} "Prepaid Sponsorship Fees": {}
} }
} }
}, },
"Long Term Assets": { "Long Term Assets": {
"Fixed Assets": { "Fixed Assets": {
"Accumulated Depreciation": { "Accumulated Depreciation": {
"Acc. Depreciation of Motor Vehicles": { "Acc. Depreciation of Motor Vehicles": {
"account_type": "Accumulated Depreciation" "account_type": "Accumulated Depreciation"
}, },
"Acc. Deprn.Computer Hardware & Software": { "Acc. Deprn.Computer Hardware & Software": {
"account_type": "Accumulated Depreciation" "account_type": "Accumulated Depreciation"
}, },
"Acc.Deprn.of Furniture & Office Equipment": { "Acc.Deprn.of Furniture & Office Equipment": {
"account_type": "Accumulated Depreciation" "account_type": "Accumulated Depreciation"
}, },
"Amortisation on Leasehold Improvement": { "Amortisation on Leasehold Improvement": {
"account_type": "Accumulated Depreciation" "account_type": "Accumulated Depreciation"
}, },
"account_type": "Accumulated Depreciation" "account_type": "Accumulated Depreciation"
}, },
"Fixed Assets (Cost Price)": { "Fixed Assets (Cost Price)": {
"Computer Hardware & Software": { "Computer Hardware & Software": {
"account_type": "Fixed Asset" "account_type": "Fixed Asset"
}, },
"Furniture and Equipment": { "Furniture and Equipment": {
"account_type": "Fixed Asset" "account_type": "Fixed Asset"
}, },
"Leasehold Improvement": {}, "Leasehold Improvement": {},
"Motor Vehicles": { "Motor Vehicles": {
"account_type": "Fixed Asset" "account_type": "Fixed Asset"
}, },
"Work In Progress": {}, "Work In Progress": {},
"account_type": "Fixed Asset" "account_type": "Fixed Asset"
} }
}, },
"Intangible Assets": { "Intangible Assets": {
"Computer Card Renewal": {}, "Computer Card Renewal": {},
"Disposal of Outlets": {}, "Disposal of Outlets": {},
"Registration of Trademarks": {} "Registration of Trademarks": {}
}, },
"Intercompany Accounts": {}, "Intercompany Accounts": {},
"Investments": { "Investments": {
"Investments in Subsidiaries": {} "Investments in Subsidiaries": {}
} }
}, },
"root_type": "Asset" "root_type": "Asset"
}, },
"Closing And Temporary Accounts": { "Closing And Temporary Accounts": {
"Closing Accounts": { "Closing Accounts": {
"Closing Account": {} "Closing Account": {}
}, },
"root_type": "Liability" "root_type": "Liability"
}, },
"Expenses": { "Expenses": {
"Commercial Expenses": { "Commercial Expenses": {
"Consultancy Fees": {}, "Consultancy Fees": {},
"Provision for Doubtful Debts": {} "Provision for Doubtful Debts": {}
}, },
"Cost of Sale": { "Cost of Sale": {
"Cost Of Goods Sold": { "Cost Of Goods Sold": {
"Cost Of Goods Sold I/C Sales": {}, "Cost Of Goods Sold I/C Sales": {},
"Cost of Goods Sold in Trading": { "Cost of Goods Sold in Trading": {
"account_type": "Cost of Goods Sold" "account_type": "Cost of Goods Sold"
}, },
"account_type": "Cost of Goods Sold" "account_type": "Cost of Goods Sold"
}, },
"Expenses Included In Valuation": { "Expenses Included In Valuation": {
"account_type": "Expenses Included In Valuation" "account_type": "Expenses Included In Valuation"
},
"Stock Adjustment": {
"account_type": "Stock Adjustment"
} }
}, },
"Depreciation": { "Depreciation": {
"Depreciation & Amortization": { "Depreciation & Amortization": {
"Amortization on Leasehold Improvement": {}, "Amortization on Leasehold Improvement": {},
"Depreciation Of Computer Hard & Soft": { "Depreciation Of Computer Hard & Soft": {
"account_type": "Depreciation" "account_type": "Depreciation"
}, },
"Depreciation Of Furniture & Office Equipment\n\t\t\t": { "Depreciation Of Furniture & Office Equipment\n\t\t\t": {
"account_type": "Depreciation" "account_type": "Depreciation"
}, },
"Depreciation Of Motor Vehicles": { "Depreciation Of Motor Vehicles": {
"account_type": "Depreciation" "account_type": "Depreciation"
} }
} }
}, },
"Direct Expenses": { "Direct Expenses": {
"Financial Charges": { "Financial Charges": {
"Air Miles Card Charges": {}, "Air Miles Card Charges": {},
"Amex Credit Cards Charges": {}, "Amex Credit Cards Charges": {},
"Bank Finance & Loan Charges": {}, "Bank Finance & Loan Charges": {},
"Credit Card Charges": {}, "Credit Card Charges": {},
"Credit Card Swipe Charges": {}, "Credit Card Swipe Charges": {},
"PayPal Charges": {} "PayPal Charges": {}
} }
}, },
"MISC Charges": { "MISC Charges": {
"Other Charges": { "Other Charges": {
"Capital Loss": { "Capital Loss": {
"Disposal of Business Branch": {}, "Disposal of Business Branch": {},
"Loss On Fixed Assets Disposal": {}, "Loss On Fixed Assets Disposal": {},
"Loss on Difference on Exchange": {} "Loss on Difference on Exchange": {}
}, },
"Other Non Operating Exp": { "Other Non Operating Exp": {
"Other Non Operating Expenses": {} "Other Non Operating Expenses": {}
}, },
"Previous Year Adjustments": { "Previous Year Adjustments": {
"Previous Year Adjustments Account": {} "Previous Year Adjustments Account": {}
}, },
"Royalty Fees": { "Royalty Fees": {
"Royalty to Parent Co.": {} "Royalty to Parent Co.": {}
}, },
"Tax / Zakat Expenses": { "Tax / Zakat Expenses": {
"Income Tax": { "Income Tax": {
"account_type": "Tax" "account_type": "Tax"
}, },
"Zakat": {}, "Zakat": {},
"account_type": "Tax" "account_type": "Tax"
} }
} }
}, },
"Share Resources": { "Share Resources": {
"Share Resource Expenses Account": {} "Share Resource Expenses Account": {}
}, },
"Store Operating Expenses": { "Store Operating Expenses": {
"Selling, General & Admin Expenses": { "Selling, General & Admin Expenses": {
"Advertising Expenses": { "Advertising Expenses": {
"Other - Advertising Expenses": {} "Other - Advertising Expenses": {}
}, },
"Bank & Finance Charges": { "Bank & Finance Charges": {
"Other Bank Charges": {} "Other Bank Charges": {}
}, },
"Communications": { "Communications": {
"Courier": {}, "Courier": {},
"Others - Communication": {}, "Others - Communication": {},
"Telephone": {}, "Telephone": {},
"Web Site Hosting Fees": {} "Web Site Hosting Fees": {}
}, },
"Office & Various Expenses": { "Office & Various Expenses": {
"Cleaning": {}, "Cleaning": {},
"Conveyance Expenses": {}, "Conveyance Expenses": {},
"Gifts & Donations": {}, "Gifts & Donations": {},
"Insurance": {}, "Insurance": {},
"Kitchen and Buffet Expenses": {}, "Kitchen and Buffet Expenses": {},
"Maintenance": {}, "Maintenance": {},
"Others - Office Various Expenses": {}, "Others - Office Various Expenses": {},
"Security & Guard": {}, "Security & Guard": {},
"Stationary From Suppliers": {}, "Stationary From Suppliers": {},
"Stationary Out Of Stock": {}, "Stationary Out Of Stock": {},
"Subscriptions": {}, "Subscriptions": {},
"Training": {}, "Training": {},
"Vehicle Expenses": {} "Vehicle Expenses": {}
}, },
"Personnel Cost": { "Personnel Cost": {
"Basic Salary": {}, "Basic Salary": {},
"End Of Service Indemnity": {}, "End Of Service Indemnity": {},
"Housing Allowance": {}, "Housing Allowance": {},
"Leave Salary": {}, "Leave Salary": {},
"Leave Ticket": {}, "Leave Ticket": {},
"Life Insurance": {}, "Life Insurance": {},
"Medical Insurance": {}, "Medical Insurance": {},
"Personnel Cost Others": {}, "Personnel Cost Others": {},
"Sales Commission": {}, "Sales Commission": {},
"Staff School Allowances": {}, "Staff School Allowances": {},
"Transportation Allowance": {}, "Transportation Allowance": {},
"Uniform": {}, "Uniform": {},
"Visa Expenses": {} "Visa Expenses": {}
}, },
"Professional & Legal Fees": { "Professional & Legal Fees": {
"Audit Fees": {}, "Audit Fees": {},
"Legal fees": {}, "Legal fees": {},
"Others - Professional Fees": {}, "Others - Professional Fees": {},
"Sponsorship Fees": {}, "Sponsorship Fees": {},
"Trade License Fees": {} "Trade License Fees": {}
}, },
"Provision & Write Off": { "Provision & Write Off": {
"Amortisation of Preoperating Expenses": {}, "Amortisation of Preoperating Expenses": {},
"Cash Shortage": {}, "Cash Shortage": {},
"Others - Provision & Write off": {}, "Others - Provision & Write off": {},
"Write Off Inventory": {}, "Write Off Inventory": {},
"Write Off Receivables & Payables": {} "Write Off Receivables & Payables": {}
}, },
"Rent Expenses": { "Rent Expenses": {
"Office Rent": {}, "Office Rent": {},
"Warehouse Rent": {} "Warehouse Rent": {}
}, },
"Travel Expenses": { "Travel Expenses": {
"Air tickets": {}, "Air tickets": {},
"Hotel": {}, "Hotel": {},
"Meals": {}, "Meals": {},
"Others": {}, "Others": {},
"Per Diem": {} "Per Diem": {}
}, },
"Utilities": { "Utilities": {
"Other Utility Cahrges": {}, "Other Utility Cahrges": {},
"Water & Electricity": {} "Water & Electricity": {}
} }
} }
}, },
"root_type": "Expense" "root_type": "Expense"
}, },
"Liabilities": { "Liabilities": {
"Current Liabilities": { "Current Liabilities": {
"Accounts Payable": { "Accounts Payable": {
"Payables": { "Payables": {
"Advance Payable to Suppliers": { "Advance Payable to Suppliers": {
"account_type": "Payable" "account_type": "Payable"
}, },
"Consigned Payable": { "Consigned Payable": {
"account_type": "Payable" "account_type": "Payable"
}, },
"Other Payable": { "Other Payable": {
"account_type": "Payable" "account_type": "Payable"
}, },
"Post Dated Cheques Paid": { "Post Dated Cheques Paid": {
"account_type": "Payable" "account_type": "Payable"
}, },
"Staff Payable": {}, "Staff Payable": {},
"Suppliers Price Protection": { "Suppliers Price Protection": {
"account_type": "Payable" "account_type": "Payable"
}, },
"Trade Payable": { "Trade Payable": {
"account_type": "Payable" "account_type": "Payable"
}, },
"account_type": "Payable" "account_type": "Payable"
} }
}, },
"Accruals & Provisions": { "Accruals & Provisions": {
"Accruals": { "Accruals": {
"Accrued Personnel Cost": { "Accrued Personnel Cost": {
"Accrued - Commissions": {}, "Accrued - Commissions": {},
"Accrued - Leave Salary": {}, "Accrued - Leave Salary": {},
"Accrued - Leave Tickets": {}, "Accrued - Leave Tickets": {},
"Accrued - Salaries": {}, "Accrued - Salaries": {},
"Accrued Other Personnel Cost": {}, "Accrued Other Personnel Cost": {},
"Accrued Salaries Increment": {}, "Accrued Salaries Increment": {},
"Accrued-Staff Bonus": {} "Accrued-Staff Bonus": {}
} }
}, },
"Accrued Expenses": { "Accrued Expenses": {
"Accrued Other Expenses": { "Accrued Other Expenses": {
"Accrued - Audit Fees": {}, "Accrued - Audit Fees": {},
"Accrued - Office Rent": {}, "Accrued - Office Rent": {},
"Accrued - Sponsorship": {}, "Accrued - Sponsorship": {},
"Accrued - Telephone": {}, "Accrued - Telephone": {},
"Accrued - Utilities": {}, "Accrued - Utilities": {},
"Accrued Others": {} "Accrued Others": {}
} }
}, },
"Other Current Liabilities": { "Other Current Liabilities": {
"Accrued Dubai Customs": {}, "Accrued Dubai Customs": {},
"Deferred income": {}, "Deferred income": {},
"Shipping & Handling": {} "Shipping & Handling": {}
}, },
"Provisions": { "Provisions": {
"Tax Payables": { "Tax Payables": {
"Income Tax Payable": {}, "Income Tax Payable": {},
"Sales Tax Payable": {}, "Sales Tax Payable": {},
"Withholding Tax Payable": {} "Withholding Tax Payable": {}
} }
}, },
"Short Term Loan": {} "Short Term Loan": {}
}, },
"Duties and Taxes": { "Duties and Taxes": {
"account_type": "Tax", "account_type": "Tax",
"is_group": 1 "is_group": 1
}, },
"Reservations & Credit Notes": { "Reservations & Credit Notes": {
"Credit Notes": { "Credit Notes": {
"Credit Notes to Customers": {}, "Credit Notes to Customers": {},
"Reservations": {} "Reservations": {}
} }
}, },
"Stock Liabilities": { "Stock Liabilities": {
"Stock Received But Not Billed": { "Stock Received But Not Billed": {
"account_type": "Stock Received But Not Billed" "account_type": "Stock Received But Not Billed"
} }
}, },
"Unearned Income": {} "Unearned Income": {}
}, },
"Long Term Liabilities": { "Long Term Liabilities": {
"Long Term Loans & Provisions": {} "Long Term Loans & Provisions": {}
}, },
"root_type": "Liability" "root_type": "Liability"
}, },
"Revenue": { "Revenue": {
"Direct Revenue": { "Direct Revenue": {
"Other Direct Revenue": { "Other Direct Revenue": {
"Other Revenue - Operating": { "Other Revenue - Operating": {
"Advertising Income": {}, "Advertising Income": {},
"Branding Income": {}, "Branding Income": {},
"Early Setmt Margin from Suppliers": {}, "Early Setmt Margin from Suppliers": {},
"Marketing Rebate from Suppliers": {}, "Marketing Rebate from Suppliers": {},
"Rebate from Suppliers": {}, "Rebate from Suppliers": {},
"Service Income": {}, "Service Income": {},
"Space Rental Income": {} "Space Rental Income": {}
} }
} }
}, },
"Indirect Revenue": { "Indirect Revenue": {
"Other Indirect Revenue": { "Other Indirect Revenue": {
"Capital Gain": {}, "Capital Gain": {},
"Excess In Till": {}, "Excess In Till": {},
"Gain On Difference Of Exchange": {}, "Gain On Difference Of Exchange": {},
"Management Consultancy Fees": {}, "Management Consultancy Fees": {},
"Other Income": {} "Other Income": {}
}, },
"Other Revenue - Non Operating": { "Other Revenue - Non Operating": {
"Interest Revenue": {}, "Interest Revenue": {},
"Interest from FD": {}, "Interest from FD": {},
"Products Listing Fees from Suppliers": {}, "Products Listing Fees from Suppliers": {},
"Trade Opening Fees from suppliers": {} "Trade Opening Fees from suppliers": {}
} }
}, },
"Sales": { "Sales": {
"Sales from Other Regions": { "Sales from Other Regions": {
"Sales from Other Region": {} "Sales from Other Region": {}
}, },
"Sales of same region": { "Sales of same region": {
"Management Consultancy Fees 1": {}, "Management Consultancy Fees 1": {},
"Sales Account": {}, "Sales Account": {},
"Sales of I/C": {} "Sales of I/C": {}
} }
}, },
"root_type": "Income" "root_type": "Income"
}, },
"Share Holder Equity": { "Share Holder Equity": {
"Capital": { "Capital": {
"Contributed Capital": {}, "Contributed Capital": {},
"Share Capital": {}, "Share Capital": {},
"Shareholders Current A/c": {}, "Shareholders Current A/c": {},
"Sub Ordinated Loan": {}, "Sub Ordinated Loan": {},
"Treasury Stocks": {} "Treasury Stocks": {}
}, },
"Retained Earnings": { "Retained Earnings": {
"Current Year Results": {}, "Current Year Results": {},
"Dividends Paid": {}, "Dividends Paid": {},
"Previous Years Results": {} "Previous Years Results": {}
}, },
"account_type": "Equity", "account_type": "Equity",
"root_type": "Equity" "root_type": "Equity"
} }
} }

View File

@ -185,7 +185,8 @@ def validate_account_types(accounts):
return _("Please identify/create Account (Ledger) for type - {0}").format(' , '.join(missing)) return _("Please identify/create Account (Ledger) for type - {0}").format(' , '.join(missing))
account_types_for_group = ["Bank", "Cash", "Stock"] account_types_for_group = ["Bank", "Cash", "Stock"]
account_groups = [accounts[d]["account_type"] for d in accounts if accounts[d]['is_group'] not in ('', 1)] # fix logic bug
account_groups = [accounts[d]["account_type"] for d in accounts if accounts[d]['is_group'] == 1]
missing = list(set(account_types_for_group) - set(account_groups)) missing = list(set(account_types_for_group) - set(account_groups))
if missing: if missing:

View File

@ -18,6 +18,7 @@ class CostCenter(NestedSet):
def validate(self): def validate(self):
self.validate_mandatory() self.validate_mandatory()
self.validate_parent_cost_center()
def validate_mandatory(self): def validate_mandatory(self):
if self.cost_center_name != self.company and not self.parent_cost_center: if self.cost_center_name != self.company and not self.parent_cost_center:
@ -25,6 +26,12 @@ class CostCenter(NestedSet):
elif self.cost_center_name == self.company and self.parent_cost_center: elif self.cost_center_name == self.company and self.parent_cost_center:
frappe.throw(_("Root cannot have a parent cost center")) frappe.throw(_("Root cannot have a parent cost center"))
def validate_parent_cost_center(self):
if self.parent_cost_center:
if not frappe.db.get_value('Cost Center', self.parent_cost_center, 'is_group'):
frappe.throw(_("{0} is not a group node. Please select a group node as parent cost center").format(
frappe.bold(self.parent_cost_center)))
def convert_group_to_ledger(self): def convert_group_to_ledger(self):
if self.check_if_child_exists(): if self.check_if_child_exists():
frappe.throw(_("Cannot convert Cost Center to ledger as it has child nodes")) frappe.throw(_("Cannot convert Cost Center to ledger as it has child nodes"))

View File

@ -1,12 +1,26 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt # License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals from __future__ import unicode_literals
import unittest
import frappe import frappe
test_records = frappe.get_test_records('Cost Center') test_records = frappe.get_test_records('Cost Center')
class TestCostCenter(unittest.TestCase):
def test_cost_center_creation_against_child_node(self):
if not frappe.db.get_value('Cost Center', {'name': '_Test Cost Center 2 - _TC'}):
frappe.get_doc(test_records[1]).insert()
cost_center = frappe.get_doc({
'doctype': 'Cost Center',
'cost_center_name': '_Test Cost Center 3',
'parent_cost_center': '_Test Cost Center 2 - _TC',
'is_group': 0,
'company': '_Test Company'
})
self.assertRaises(frappe.ValidationError, cost_center.save)
def create_cost_center(**args): def create_cost_center(**args):
args = frappe._dict(args) args = frappe._dict(args)

View File

@ -330,23 +330,6 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
frm: cur_frm frm: cur_frm
}) })
}, },
item_code: function(frm, cdt, cdn) {
var row = locals[cdt][cdn];
if(row.item_code) {
frappe.call({
method: "erpnext.assets.doctype.asset_category.asset_category.get_asset_category_account",
args: {
"item": row.item_code,
"fieldname": "fixed_asset_account",
"company": frm.doc.company
},
callback: function(r, rt) {
frappe.model.set_value(cdt, cdn, "expense_account", r.message);
}
})
}
}
}); });
cur_frm.script_manager.make(erpnext.accounts.PurchaseInvoice); cur_frm.script_manager.make(erpnext.accounts.PurchaseInvoice);

View File

@ -789,22 +789,21 @@ frappe.ui.form.on('Sales Invoice', {
method: "frappe.client.get_value", method: "frappe.client.get_value",
args:{ args:{
doctype: "Patient", doctype: "Patient",
filters: {"name": frm.doc.patient}, filters: {
"name": frm.doc.patient
},
fieldname: "customer" fieldname: "customer"
}, },
callback:function(patient_customer) { callback:function(r) {
if(patient_customer){ if(r && r.message.customer){
frm.set_value("customer", patient_customer.message.customer); frm.set_value("customer", r.message.customer);
frm.refresh_fields();
} }
} }
}); });
} }
else{
frm.set_value("customer", '');
}
} }
}, },
refresh: function(frm) { refresh: function(frm) {
if (frappe.boot.active_domains.includes("Healthcare")){ if (frappe.boot.active_domains.includes("Healthcare")){
frm.set_df_property("patient", "hidden", 0); frm.set_df_property("patient", "hidden", 0);

View File

@ -1048,13 +1048,18 @@ class SalesInvoice(SellingController):
continue continue
for serial_no in item.serial_no.split("\n"): for serial_no in item.serial_no.split("\n"):
sales_invoice, item_code = frappe.db.get_value("Serial No", serial_no, serial_no_details = frappe.db.get_value("Serial No", serial_no,
["sales_invoice", "item_code"]) ["sales_invoice", "item_code"], as_dict=1)
if sales_invoice and item_code == item.item_code and self.name != sales_invoice:
sales_invoice_company = frappe.db.get_value("Sales Invoice", sales_invoice, "company") if not serial_no_details:
continue
if serial_no_details.sales_invoice and serial_no_details.item_code == item.item_code \
and self.name != serial_no_details.sales_invoice:
sales_invoice_company = frappe.db.get_value("Sales Invoice", serial_no_details.sales_invoice, "company")
if sales_invoice_company == self.company: if sales_invoice_company == self.company:
frappe.throw(_("Serial Number: {0} is already referenced in Sales Invoice: {1}" frappe.throw(_("Serial Number: {0} is already referenced in Sales Invoice: {1}"
.format(serial_no, sales_invoice))) .format(serial_no, serial_no_details.sales_invoice)))
def update_project(self): def update_project(self):
if self.project: if self.project:

View File

@ -70,7 +70,7 @@ class ShippingRule(Document):
def get_shipping_amount_from_rules(self, value): def get_shipping_amount_from_rules(self, value):
for condition in self.get("conditions"): for condition in self.get("conditions"):
if not condition.to_value or (flt(condition.from_value) <= value <= flt(condition.to_value)): if not condition.to_value or (flt(condition.from_value) <= flt(value) <= flt(condition.to_value)):
return condition.shipping_amount return condition.shipping_amount
return 0.0 return 0.0

View File

@ -162,33 +162,34 @@ def validate_account_for_perpetual_inventory(gl_map):
frappe.throw(_("Account: {0} can only be updated via Stock Transactions") frappe.throw(_("Account: {0} can only be updated via Stock Transactions")
.format(account), StockAccountInvalidTransaction) .format(account), StockAccountInvalidTransaction)
elif account_bal != stock_bal: # This has been comment for a temporary, will add this code again on release of immutable ledger
precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"), # elif account_bal != stock_bal:
currency=frappe.get_cached_value('Company', gl_map[0].company, "default_currency")) # precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"),
# currency=frappe.get_cached_value('Company', gl_map[0].company, "default_currency"))
diff = flt(stock_bal - account_bal, precision) # diff = flt(stock_bal - account_bal, precision)
error_reason = _("Stock Value ({0}) and Account Balance ({1}) are out of sync for account {2} and it's linked warehouses.").format( # error_reason = _("Stock Value ({0}) and Account Balance ({1}) are out of sync for account {2} and it's linked warehouses.").format(
stock_bal, account_bal, frappe.bold(account)) # stock_bal, account_bal, frappe.bold(account))
error_resolution = _("Please create adjustment Journal Entry for amount {0} ").format(frappe.bold(diff)) # error_resolution = _("Please create adjustment Journal Entry for amount {0} ").format(frappe.bold(diff))
stock_adjustment_account = frappe.db.get_value("Company",gl_map[0].company,"stock_adjustment_account") # stock_adjustment_account = frappe.db.get_value("Company",gl_map[0].company,"stock_adjustment_account")
db_or_cr_warehouse_account =('credit_in_account_currency' if diff < 0 else 'debit_in_account_currency') # db_or_cr_warehouse_account =('credit_in_account_currency' if diff < 0 else 'debit_in_account_currency')
db_or_cr_stock_adjustment_account = ('debit_in_account_currency' if diff < 0 else 'credit_in_account_currency') # db_or_cr_stock_adjustment_account = ('debit_in_account_currency' if diff < 0 else 'credit_in_account_currency')
journal_entry_args = { # journal_entry_args = {
'accounts':[ # 'accounts':[
{'account': account, db_or_cr_warehouse_account : abs(diff)}, # {'account': account, db_or_cr_warehouse_account : abs(diff)},
{'account': stock_adjustment_account, db_or_cr_stock_adjustment_account : abs(diff) }] # {'account': stock_adjustment_account, db_or_cr_stock_adjustment_account : abs(diff) }]
} # }
frappe.msgprint(msg="""{0}<br></br>{1}<br></br>""".format(error_reason, error_resolution), # frappe.msgprint(msg="""{0}<br></br>{1}<br></br>""".format(error_reason, error_resolution),
raise_exception=StockValueAndAccountBalanceOutOfSync, # raise_exception=StockValueAndAccountBalanceOutOfSync,
title=_('Values Out Of Sync'), # title=_('Values Out Of Sync'),
primary_action={ # primary_action={
'label': _('Make Journal Entry'), # 'label': _('Make Journal Entry'),
'client_action': 'erpnext.route_to_adjustment_jv', # 'client_action': 'erpnext.route_to_adjustment_jv',
'args': journal_entry_args # 'args': journal_entry_args
}) # })
def validate_cwip_accounts(gl_map): def validate_cwip_accounts(gl_map):
cwip_enabled = any([cint(ac.enable_cwip_accounting) for ac in frappe.db.get_all("Asset Category","enable_cwip_accounting")]) cwip_enabled = any([cint(ac.enable_cwip_accounting) for ac in frappe.db.get_all("Asset Category","enable_cwip_accounting")])

View File

@ -100,6 +100,11 @@ frappe.query_reports["Accounts Payable"] = {
"fieldtype": "Link", "fieldtype": "Link",
"options": "Supplier Group" "options": "Supplier Group"
}, },
{
"fieldname":"based_on_payment_terms",
"label": __("Based On Payment Terms"),
"fieldtype": "Check",
},
{ {
"fieldname":"tax_id", "fieldname":"tax_id",
"label": __("Tax Id"), "label": __("Tax Id"),

View File

@ -318,7 +318,7 @@ class ReceivablePayableReport(object):
self.append_payment_term(row, d, term) self.append_payment_term(row, d, term)
def append_payment_term(self, row, d, term): def append_payment_term(self, row, d, term):
if self.filters.get("customer") and d.currency == d.party_account_currency: if (self.filters.get("customer") or self.filters.get("supplier")) and d.currency == d.party_account_currency:
invoiced = d.payment_amount invoiced = d.payment_amount
else: else:
invoiced = flt(flt(d.payment_amount) * flt(d.conversion_rate), self.currency_precision) invoiced = flt(flt(d.payment_amount) * flt(d.conversion_rate), self.currency_precision)

View File

@ -569,7 +569,7 @@ def get_stock_and_account_balance(account=None, posting_date=None, company=None)
warehouse_account = get_warehouse_account_map(company) warehouse_account = get_warehouse_account_map(company)
account_balance = get_balance_on(account, posting_date, in_account_currency=False) account_balance = get_balance_on(account, posting_date, in_account_currency=False, ignore_account_permission=True)
related_warehouses = [wh for wh, wh_details in warehouse_account.items() related_warehouses = [wh for wh, wh_details in warehouse_account.items()
if wh_details.account == account and not wh_details.is_group] if wh_details.account == account and not wh_details.is_group]

View File

@ -517,15 +517,18 @@ def update_maintenance_status():
asset.set_status('Out of Order') asset.set_status('Out of Order')
def make_post_gl_entry(): def make_post_gl_entry():
if not is_cwip_accounting_enabled(self.asset_category):
return
assets = frappe.db.sql_list(""" select name from `tabAsset` asset_categories = frappe.db.get_all('Asset Category', fields = ['name', 'enable_cwip_accounting'])
where ifnull(booked_fixed_asset, 0) = 0 and available_for_use_date = %s""", nowdate())
for asset in assets: for asset_category in asset_categories:
doc = frappe.get_doc('Asset', asset) if cint(asset_category.enable_cwip_accounting):
doc.make_gl_entries() assets = frappe.db.sql_list(""" select name from `tabAsset`
where asset_category = %s and ifnull(booked_fixed_asset, 0) = 0
and available_for_use_date = %s""", (asset_category.name, nowdate()))
for asset in assets:
doc = frappe.get_doc('Asset', asset)
doc.make_gl_entries()
def get_asset_naming_series(): def get_asset_naming_series():
meta = frappe.get_meta('Asset') meta = frappe.get_meta('Asset')

View File

@ -29,7 +29,8 @@ def get_asset_category_account(fieldname, item=None, asset=None, account=None, a
account=None account=None
if not account: if not account:
asset_category, company = frappe.db.get_value("Asset", asset, ["asset_category", "company"]) asset_details = frappe.db.get_value("Asset", asset, ["asset_category", "company"])
asset_category, company = asset_details or [None, None]
account = frappe.db.get_value("Asset Category Account", account = frappe.db.get_value("Asset Category Account",
filters={"parent": asset_category, "company_name": company}, fieldname=fieldname) filters={"parent": asset_category, "company_name": company}, fieldname=fieldname)

View File

@ -18,6 +18,7 @@ frappe.ui.form.on("Purchase Order", {
return { return {
filters: { filters: {
"company": frm.doc.company, "company": frm.doc.company,
"name": ['!=', frm.doc.supplier_warehouse],
"is_group": 0 "is_group": 0
} }
} }
@ -283,6 +284,8 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
}) })
} }
me.dialog.get_field('sub_con_rm_items').check_all_rows()
me.dialog.show() me.dialog.show()
this.dialog.set_primary_action(__('Transfer'), function() { this.dialog.set_primary_action(__('Transfer'), function() {
me.values = me.dialog.get_values(); me.values = me.dialog.get_values();

View File

@ -519,47 +519,62 @@ class TestPurchaseOrder(unittest.TestCase):
def test_backflush_based_on_stock_entry(self): def test_backflush_based_on_stock_entry(self):
item_code = "_Test Subcontracted FG Item 1" item_code = "_Test Subcontracted FG Item 1"
make_subcontracted_item(item_code) make_subcontracted_item(item_code)
make_item('Sub Contracted Raw Material 1', {
'is_stock_item': 1,
'is_sub_contracted_item': 1
})
update_backflush_based_on("Material Transferred for Subcontract") update_backflush_based_on("Material Transferred for Subcontract")
po = create_purchase_order(item_code=item_code, qty=1,
order_qty = 5
po = create_purchase_order(item_code=item_code, qty=order_qty,
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC") is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC")
make_stock_entry(target="_Test Warehouse - _TC", qty=10, basic_rate=100)
make_stock_entry(target="_Test Warehouse - _TC", make_stock_entry(target="_Test Warehouse - _TC",
item_code="_Test Item Home Desktop 100", qty=10, basic_rate=100) item_code="_Test Item Home Desktop 100", qty=10, basic_rate=100)
make_stock_entry(target="_Test Warehouse - _TC", make_stock_entry(target="_Test Warehouse - _TC",
item_code = "Test Extra Item 1", qty=100, basic_rate=100) item_code = "Test Extra Item 1", qty=100, basic_rate=100)
make_stock_entry(target="_Test Warehouse - _TC", make_stock_entry(target="_Test Warehouse - _TC",
item_code = "Test Extra Item 2", qty=10, basic_rate=100) item_code = "Test Extra Item 2", qty=10, basic_rate=100)
make_stock_entry(target="_Test Warehouse - _TC",
item_code = "Sub Contracted Raw Material 1", qty=10, basic_rate=100)
rm_item = [ rm_items = [
{"item_code":item_code,"rm_item_code":"_Test Item","item_name":"_Test Item", {"item_code":item_code,"rm_item_code":"Sub Contracted Raw Material 1","item_name":"_Test Item",
"qty":1,"warehouse":"_Test Warehouse - _TC","rate":100,"amount":100,"stock_uom":"Nos"}, "qty":10,"warehouse":"_Test Warehouse - _TC", "stock_uom":"Nos"},
{"item_code":item_code,"rm_item_code":"_Test Item Home Desktop 100","item_name":"_Test Item Home Desktop 100", {"item_code":item_code,"rm_item_code":"_Test Item Home Desktop 100","item_name":"_Test Item Home Desktop 100",
"qty":2,"warehouse":"_Test Warehouse - _TC","rate":100,"amount":200,"stock_uom":"Nos"}, "qty":20,"warehouse":"_Test Warehouse - _TC", "stock_uom":"Nos"},
{"item_code":item_code,"rm_item_code":"Test Extra Item 1","item_name":"Test Extra Item 1", {"item_code":item_code,"rm_item_code":"Test Extra Item 1","item_name":"Test Extra Item 1",
"qty":1,"warehouse":"_Test Warehouse - _TC","rate":100,"amount":200,"stock_uom":"Nos"}] "qty":10,"warehouse":"_Test Warehouse - _TC", "stock_uom":"Nos"},
{'item_code': item_code, 'rm_item_code': 'Test Extra Item 2', 'stock_uom':'Nos',
'qty': 10, 'warehouse': '_Test Warehouse - _TC', 'item_name':'Test Extra Item 2'}]
rm_item_string = json.dumps(rm_item) rm_item_string = json.dumps(rm_items)
se = frappe.get_doc(make_subcontract_transfer_entry(po.name, rm_item_string)) se = frappe.get_doc(make_subcontract_transfer_entry(po.name, rm_item_string))
se.append('items', {
'item_code': "Test Extra Item 2",
"qty": 1,
"rate": 100,
"s_warehouse": "_Test Warehouse - _TC",
"t_warehouse": "_Test Warehouse 1 - _TC"
})
se.set_missing_values()
se.submit() se.submit()
pr = make_purchase_receipt(po.name) pr = make_purchase_receipt(po.name)
received_qty = 2
# partial receipt
pr.get('items')[0].qty = received_qty
pr.save() pr.save()
pr.submit() pr.submit()
se_items = sorted([d.item_code for d in se.get('items')]) transferred_items = sorted([d.item_code for d in se.get('items') if se.purchase_order == po.name])
supplied_items = sorted([d.rm_item_code for d in pr.get('supplied_items')]) issued_items = sorted([d.rm_item_code for d in pr.get('supplied_items')])
self.assertEquals(transferred_items, issued_items)
self.assertEquals(pr.get('items')[0].rm_supp_cost, 2000)
transferred_rm_map = frappe._dict()
for item in rm_items:
transferred_rm_map[item.get('rm_item_code')] = item
for item in pr.get('supplied_items'):
self.assertEqual(item.get('required_qty'), (transferred_rm_map[item.get('rm_item_code')].get('qty') / order_qty) * received_qty)
self.assertEquals(se_items, supplied_items)
update_backflush_based_on("BOM") update_backflush_based_on("BOM")
def test_advance_payment_entry_unlink_against_purchase_order(self): def test_advance_payment_entry_unlink_against_purchase_order(self):

View File

@ -56,3 +56,23 @@ class Supplier(TransactionBase):
def after_rename(self, olddn, newdn, merge=False): def after_rename(self, olddn, newdn, merge=False):
if frappe.defaults.get_global_default('supp_master_name') == 'Supplier Name': if frappe.defaults.get_global_default('supp_master_name') == 'Supplier Name':
frappe.db.set(self, "supplier_name", newdn) frappe.db.set(self, "supplier_name", newdn)
def create_onboarding_docs(self, args):
defaults = frappe.defaults.get_defaults()
for i in range(1, args.get('max_count')):
supplier = args.get('supplier_name_' + str(i))
if supplier:
try:
doc = frappe.get_doc({
'doctype': self.doctype,
'supplier_name': supplier,
'supplier_group': _('Local'),
'company': defaults.get('company')
}).insert()
if args.get('supplier_email_' + str(i)):
from erpnext.selling.doctype.customer.customer import create_contact
create_contact(supplier, 'Supplier',
doc.name, args.get('supplier_email_' + str(i)))
except frappe.NameError:
pass

View File

@ -0,0 +1,49 @@
{
"add_more_button": 1,
"app": "ERPNext",
"creation": "2019-11-15 14:45:32.626641",
"docstatus": 0,
"doctype": "Setup Wizard Slide",
"domains": [],
"help_links": [
{
"label": "Supplier",
"video_id": "zsrrVDk6VBs"
}
],
"idx": 0,
"image_src": "/assets/erpnext/images/illustrations/supplier.png",
"max_count": 3,
"modified": "2019-11-26 18:26:25.498325",
"modified_by": "Administrator",
"name": "Add A Few Suppliers",
"owner": "Administrator",
"ref_doctype": "Supplier",
"slide_desc": "",
"slide_fields": [
{
"align": "",
"fieldname": "supplier_name",
"fieldtype": "Data",
"label": "Supplier Name",
"placeholder": "",
"reqd": 1
},
{
"align": "",
"fieldtype": "Column Break",
"reqd": 0
},
{
"align": "",
"fieldname": "supplier_email",
"fieldtype": "Data",
"label": "Supplier Email",
"reqd": 1
}
],
"slide_order": 50,
"slide_title": "Add A Few Suppliers",
"slide_type": "Create",
"submit_method": ""
}

View File

@ -197,6 +197,11 @@ def get_data():
"name": "Bank Reconciliation Statement", "name": "Bank Reconciliation Statement",
"is_query_report": True, "is_query_report": True,
"doctype": "Journal Entry" "doctype": "Journal Entry"
},{
"type": "page",
"name": "bank-reconciliation",
"label": _("Bank Reconciliation"),
"icon": "fa fa-bar-chart"
}, },
{ {
"type": "report", "type": "report",

View File

@ -241,6 +241,10 @@ def get_data():
"type": "doctype", "type": "doctype",
"name": "Quality Inspection Template", "name": "Quality Inspection Template",
}, },
{
"type": "doctype",
"name": "Quick Stock Balance",
},
] ]
}, },
{ {

View File

@ -221,7 +221,7 @@ class BuyingController(StockController):
"backflush_raw_materials_of_subcontract_based_on") "backflush_raw_materials_of_subcontract_based_on")
if (self.doctype == 'Purchase Receipt' and if (self.doctype == 'Purchase Receipt' and
backflush_raw_materials_based_on != 'BOM'): backflush_raw_materials_based_on != 'BOM'):
self.update_raw_materials_supplied_based_on_stock_entries(raw_material_table) self.update_raw_materials_supplied_based_on_stock_entries()
else: else:
for item in self.get("items"): for item in self.get("items"):
if self.doctype in ["Purchase Receipt", "Purchase Invoice"]: if self.doctype in ["Purchase Receipt", "Purchase Invoice"]:
@ -241,41 +241,95 @@ class BuyingController(StockController):
if self.is_subcontracted == "No" and self.get("supplied_items"): if self.is_subcontracted == "No" and self.get("supplied_items"):
self.set('supplied_items', []) self.set('supplied_items', [])
def update_raw_materials_supplied_based_on_stock_entries(self, raw_material_table): def update_raw_materials_supplied_based_on_stock_entries(self):
self.set(raw_material_table, []) self.set('supplied_items', [])
purchase_orders = [d.purchase_order for d in self.items]
if purchase_orders:
items = get_subcontracted_raw_materials_from_se(purchase_orders)
backflushed_raw_materials = get_backflushed_subcontracted_raw_materials_from_se(purchase_orders, self.name)
for d in items: purchase_orders = set([d.purchase_order for d in self.items])
qty = d.qty - backflushed_raw_materials.get(d.item_code, 0)
rm = self.append(raw_material_table, {})
rm.rm_item_code = d.item_code
rm.item_name = d.item_name
rm.main_item_code = d.main_item_code
rm.description = d.description
rm.stock_uom = d.stock_uom
rm.required_qty = qty
rm.consumed_qty = qty
rm.serial_no = d.serial_no
rm.batch_no = d.batch_no
# get raw materials rate # qty of raw materials backflushed (for each item per purchase order)
from erpnext.stock.utils import get_incoming_rate backflushed_raw_materials_map = get_backflushed_subcontracted_raw_materials(purchase_orders)
rm.rate = get_incoming_rate({
"item_code": d.item_code,
"warehouse": self.supplier_warehouse,
"posting_date": self.posting_date,
"posting_time": self.posting_time,
"qty": -1 * qty,
"serial_no": rm.serial_no
})
if not rm.rate:
rm.rate = get_valuation_rate(d.item_code, self.supplier_warehouse,
self.doctype, self.name, currency=self.company_currency, company = self.company)
rm.amount = qty * flt(rm.rate) # qty of "finished good" item yet to be received
qty_to_be_received_map = get_qty_to_be_received(purchase_orders)
for item in self.get('items'):
# reset raw_material cost
item.rm_supp_cost = 0
# qty of raw materials transferred to the supplier
transferred_raw_materials = get_subcontracted_raw_materials_from_se(item.purchase_order, item.item_code)
non_stock_items = get_non_stock_items(item.purchase_order, item.item_code)
item_key = '{}{}'.format(item.item_code, item.purchase_order)
fg_yet_to_be_received = qty_to_be_received_map.get(item_key)
raw_material_data = backflushed_raw_materials_map.get(item_key, {})
consumed_qty = raw_material_data.get('qty', 0)
consumed_serial_nos = raw_material_data.get('serial_nos', '')
consumed_batch_nos = raw_material_data.get('batch_nos', '')
transferred_batch_qty_map = get_transferred_batch_qty_map(item.purchase_order, item.item_code)
backflushed_batch_qty_map = get_backflushed_batch_qty_map(item.purchase_order, item.item_code)
for raw_material in transferred_raw_materials + non_stock_items:
transferred_qty = raw_material.qty
rm_qty_to_be_consumed = transferred_qty - consumed_qty
# backflush all remaining transferred qty in the last Purchase Receipt
if fg_yet_to_be_received == item.qty:
qty = rm_qty_to_be_consumed
else:
qty = (rm_qty_to_be_consumed / fg_yet_to_be_received) * item.qty
if frappe.get_cached_value('UOM', raw_material.stock_uom, 'must_be_whole_number'):
qty = frappe.utils.ceil(qty)
if qty > rm_qty_to_be_consumed:
qty = rm_qty_to_be_consumed
if not qty: continue
if raw_material.serial_nos:
set_serial_nos(raw_material, consumed_serial_nos, qty)
if raw_material.batch_nos:
batches_qty = get_batches_with_qty(raw_material.rm_item_code, raw_material.main_item_code,
qty, transferred_batch_qty_map, backflushed_batch_qty_map)
for batch_data in batches_qty:
qty = batch_data['qty']
raw_material.batch_no = batch_data['batch']
self.append_raw_material_to_be_backflushed(item, raw_material, qty)
else:
self.append_raw_material_to_be_backflushed(item, raw_material, qty)
def append_raw_material_to_be_backflushed(self, fg_item_doc, raw_material_data, qty):
rm = self.append('supplied_items', {})
rm.update(raw_material_data)
rm.required_qty = qty
rm.consumed_qty = qty
if not raw_material_data.get('non_stock_item'):
from erpnext.stock.utils import get_incoming_rate
rm.rate = get_incoming_rate({
"item_code": raw_material_data.rm_item_code,
"warehouse": self.supplier_warehouse,
"posting_date": self.posting_date,
"posting_time": self.posting_time,
"qty": -1 * qty,
"serial_no": rm.serial_no
})
if not rm.rate:
rm.rate = get_valuation_rate(raw_material_data.item_code, self.supplier_warehouse,
self.doctype, self.name, currency=self.company_currency, company=self.company)
rm.amount = qty * flt(rm.rate)
fg_item_doc.rm_supp_cost += rm.amount
def update_raw_materials_supplied_based_on_bom(self, item, raw_material_table): def update_raw_materials_supplied_based_on_bom(self, item, raw_material_table):
exploded_item = 1 exploded_item = 1
@ -387,9 +441,11 @@ class BuyingController(StockController):
item_codes = list(set(item.item_code for item in item_codes = list(set(item.item_code for item in
self.get("items"))) self.get("items")))
if item_codes: if item_codes:
self._sub_contracted_items = [r[0] for r in frappe.db.sql("""select name items = frappe.get_all('Item', filters={
from `tabItem` where name in (%s) and is_sub_contracted_item=1""" % \ 'name': ['in', item_codes],
(", ".join((["%s"]*len(item_codes))),), item_codes)] 'is_sub_contracted_item': 1
})
self._sub_contracted_items = [item.name for item in items]
return self._sub_contracted_items return self._sub_contracted_items
@ -722,28 +778,72 @@ def get_items_from_bom(item_code, bom, exploded_item=1):
return bom_items return bom_items
def get_subcontracted_raw_materials_from_se(purchase_orders): def get_subcontracted_raw_materials_from_se(purchase_order, fg_item):
return frappe.db.sql(""" common_query = """
select SELECT
sed.item_name, sed.item_code, sum(sed.qty) as qty, sed.description, sed.item_code AS rm_item_code,
sed.stock_uom, sed.subcontracted_item as main_item_code, sed.serial_no, sed.batch_no SUM(sed.qty) AS qty,
from `tabStock Entry` se,`tabStock Entry Detail` sed sed.description,
where sed.stock_uom,
se.name = sed.parent and se.docstatus=1 and se.purpose='Send to Subcontractor' sed.subcontracted_item AS main_item_code,
and se.purchase_order in (%s) and ifnull(sed.t_warehouse, '') != '' {serial_no_concat_syntax} AS serial_nos,
group by sed.item_code, sed.t_warehouse {batch_no_concat_syntax} AS batch_nos
""" % (','.join(['%s'] * len(purchase_orders))), tuple(purchase_orders), as_dict=1) FROM `tabStock Entry` se,`tabStock Entry Detail` sed
WHERE
se.name = sed.parent
AND se.docstatus=1
AND se.purpose='Send to Subcontractor'
AND se.purchase_order = %s
AND IFNULL(sed.t_warehouse, '') != ''
AND sed.subcontracted_item = %s
GROUP BY sed.item_code, sed.subcontracted_item
"""
raw_materials = frappe.db.multisql({
'mariadb': common_query.format(
serial_no_concat_syntax="GROUP_CONCAT(sed.serial_no)",
batch_no_concat_syntax="GROUP_CONCAT(sed.batch_no)"
),
'postgres': common_query.format(
serial_no_concat_syntax="STRING_AGG(sed.serial_no, ',')",
batch_no_concat_syntax="STRING_AGG(sed.batch_no, ',')"
)
}, (purchase_order, fg_item), as_dict=1)
def get_backflushed_subcontracted_raw_materials_from_se(purchase_orders, purchase_receipt): return raw_materials
return frappe._dict(frappe.db.sql("""
select def get_backflushed_subcontracted_raw_materials(purchase_orders):
prsi.rm_item_code as item_code, sum(prsi.consumed_qty) as qty common_query = """
from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pri, `tabPurchase Receipt Item Supplied` prsi SELECT
where CONCAT(prsi.rm_item_code, pri.purchase_order) AS item_key,
pr.name = pri.parent and pr.name = prsi.parent and pri.purchase_order in (%s) SUM(prsi.consumed_qty) AS qty,
and pri.item_code = prsi.main_item_code and pr.name != '%s' and pr.docstatus = 1 {serial_no_concat_syntax} AS serial_nos,
group by prsi.rm_item_code {batch_no_concat_syntax} AS batch_nos
""" % (','.join(['%s'] * len(purchase_orders)), purchase_receipt), tuple(purchase_orders))) FROM `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pri, `tabPurchase Receipt Item Supplied` prsi
WHERE
pr.name = pri.parent
AND pr.name = prsi.parent
AND pri.purchase_order IN %s
AND pri.item_code = prsi.main_item_code
AND pr.docstatus = 1
GROUP BY prsi.rm_item_code, pri.purchase_order
"""
backflushed_raw_materials = frappe.db.multisql({
'mariadb': common_query.format(
serial_no_concat_syntax="GROUP_CONCAT(prsi.serial_no)",
batch_no_concat_syntax="GROUP_CONCAT(prsi.batch_no)"
),
'postgres': common_query.format(
serial_no_concat_syntax="STRING_AGG(prsi.serial_no, ',')",
batch_no_concat_syntax="STRING_AGG(prsi.batch_no, ',')"
)
}, (purchase_orders, ), as_dict=1)
backflushed_raw_materials_map = frappe._dict()
for item in backflushed_raw_materials:
backflushed_raw_materials_map.setdefault(item.item_key, item)
return backflushed_raw_materials_map
def get_asset_item_details(asset_items): def get_asset_item_details(asset_items):
asset_items_data = {} asset_items_data = {}
@ -776,3 +876,125 @@ def validate_item_type(doc, fieldname, message):
error_message = _("Following item {0} is not marked as {1} item. You can enable them as {1} item from its Item master".format(items, message)) error_message = _("Following item {0} is not marked as {1} item. You can enable them as {1} item from its Item master".format(items, message))
frappe.throw(error_message) frappe.throw(error_message)
def get_qty_to_be_received(purchase_orders):
return frappe._dict(frappe.db.sql("""
SELECT CONCAT(poi.`item_code`, poi.`parent`) AS item_key,
SUM(poi.`qty`) - SUM(poi.`received_qty`) AS qty_to_be_received
FROM `tabPurchase Order Item` poi
WHERE
poi.`parent` in %s
GROUP BY poi.`item_code`, poi.`parent`
HAVING SUM(poi.`qty`) > SUM(poi.`received_qty`)
""", (purchase_orders)))
def get_non_stock_items(purchase_order, fg_item_code):
return frappe.db.sql("""
SELECT
pois.main_item_code,
pois.rm_item_code,
item.description,
pois.required_qty AS qty,
pois.rate,
1 as non_stock_item,
pois.stock_uom
FROM `tabPurchase Order Item Supplied` pois, `tabItem` item
WHERE
pois.`rm_item_code` = item.`name`
AND item.is_stock_item = 0
AND pois.`parent` = %s
AND pois.`main_item_code` = %s
""", (purchase_order, fg_item_code), as_dict=1)
def set_serial_nos(raw_material, consumed_serial_nos, qty):
serial_nos = set(get_serial_nos(raw_material.serial_nos)) - \
set(get_serial_nos(consumed_serial_nos))
if serial_nos and qty <= len(serial_nos):
raw_material.serial_no = '\n'.join(list(serial_nos)[0:frappe.utils.cint(qty)])
def get_transferred_batch_qty_map(purchase_order, fg_item):
# returns
# {
# (item_code, fg_code): {
# batch1: 10, # qty
# batch2: 16
# },
# }
transferred_batch_qty_map = {}
transferred_batches = frappe.db.sql("""
SELECT
sed.batch_no,
SUM(sed.qty) AS qty,
sed.item_code
FROM `tabStock Entry` se,`tabStock Entry Detail` sed
WHERE
se.name = sed.parent
AND se.docstatus=1
AND se.purpose='Send to Subcontractor'
AND se.purchase_order = %s
AND sed.subcontracted_item = %s
AND sed.batch_no IS NOT NULL
GROUP BY
sed.batch_no,
sed.item_code
""", (purchase_order, fg_item), as_dict=1)
for batch_data in transferred_batches:
transferred_batch_qty_map.setdefault((batch_data.item_code, fg_item), {})
transferred_batch_qty_map[(batch_data.item_code, fg_item)][batch_data.batch_no] = batch_data.qty
return transferred_batch_qty_map
def get_backflushed_batch_qty_map(purchase_order, fg_item):
# returns
# {
# (item_code, fg_code): {
# batch1: 10, # qty
# batch2: 16
# },
# }
backflushed_batch_qty_map = {}
backflushed_batches = frappe.db.sql("""
SELECT
pris.batch_no,
SUM(pris.consumed_qty) AS qty,
pris.rm_item_code AS item_code
FROM `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pri, `tabPurchase Receipt Item Supplied` pris
WHERE
pr.name = pri.parent
AND pri.parent = pris.parent
AND pri.purchase_order = %s
AND pri.item_code = pris.main_item_code
AND pr.docstatus = 1
AND pris.main_item_code = %s
AND pris.batch_no IS NOT NULL
GROUP BY
pris.rm_item_code, pris.batch_no
""", (purchase_order, fg_item), as_dict=1)
for batch_data in backflushed_batches:
backflushed_batch_qty_map.setdefault((batch_data.item_code, fg_item), {})
backflushed_batch_qty_map[(batch_data.item_code, fg_item)][batch_data.batch_no] = batch_data.qty
return backflushed_batch_qty_map
def get_batches_with_qty(item_code, fg_item, required_qty, transferred_batch_qty_map, backflushed_batch_qty_map):
# Returns available batches to be backflushed based on requirements
transferred_batches = transferred_batch_qty_map.get((item_code, fg_item), {})
backflushed_batches = backflushed_batch_qty_map.get((item_code, fg_item), {})
available_batches = []
for (batch, transferred_qty) in transferred_batches.items():
backflushed_qty = backflushed_batches.get(batch, 0)
available_qty = transferred_qty - backflushed_qty
if available_qty >= required_qty:
available_batches.append({'batch': batch, 'qty': required_qty})
break
else:
available_batches.append({'batch': batch, 'qty': available_qty})
required_qty -= available_qty
return available_batches

View File

@ -71,7 +71,7 @@ class ProgramEnrollment(Document):
def create_course_enrollments(self): def create_course_enrollments(self):
student = frappe.get_doc("Student", self.student) student = frappe.get_doc("Student", self.student)
program = frappe.get_doc("Program", self.program) program = frappe.get_doc("Program", self.program)
course_list = [course.course for course in program.get_all_children()] course_list = [course.course for course in program.courses]
for course_name in course_list: for course_name in course_list:
student.enroll_in_course(course_name=course_name, program_enrollment=self.name) student.enroll_in_course(course_name=course_name, program_enrollment=self.name)

View File

@ -63,10 +63,11 @@ def updating_rate(self):
item_code=%s""",(self.template, self.rate, self.item)) item_code=%s""",(self.template, self.rate, self.item))
def create_item_from_template(doc): def create_item_from_template(doc):
disabled = 1
if(doc.is_billable == 1): if(doc.is_billable == 1):
disabled = 0 disabled = 0
else:
disabled = 1
#insert item #insert item
item = frappe.get_doc({ item = frappe.get_doc({
"doctype": "Item", "doctype": "Item",

View File

@ -5,7 +5,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
from frappe import _ from frappe import _
from frappe.utils import today, now_datetime from frappe.utils import today, now_datetime, getdate
from frappe.model.document import Document from frappe.model.document import Document
from frappe.desk.reportview import get_match_cond from frappe.desk.reportview import get_match_cond
@ -15,11 +15,20 @@ class InpatientRecord(Document):
frappe.db.set_value("Patient", self.patient, "inpatient_record", self.name) frappe.db.set_value("Patient", self.patient, "inpatient_record", self.name)
def validate(self): def validate(self):
self.validate_dates()
self.validate_already_scheduled_or_admitted() self.validate_already_scheduled_or_admitted()
if self.status == "Discharged": if self.status == "Discharged":
frappe.db.set_value("Patient", self.patient, "inpatient_status", None) frappe.db.set_value("Patient", self.patient, "inpatient_status", None)
frappe.db.set_value("Patient", self.patient, "inpatient_record", None) frappe.db.set_value("Patient", self.patient, "inpatient_record", None)
def validate_dates(self):
if (getdate(self.scheduled_date) < getdate(today())) or \
(getdate(self.admitted_datetime) < getdate(today())):
frappe.throw(_("Scheduled and Admitted dates can not be less than today"))
if (getdate(self.expected_discharge) < getdate(self.scheduled_date)) or \
(getdate(self.discharge_date) < getdate(self.scheduled_date)):
frappe.throw(_("Expected and Discharge dates cannot be less than Admission Schedule date"))
def validate_already_scheduled_or_admitted(self): def validate_already_scheduled_or_admitted(self):
query = """ query = """
select name, status select name, status

View File

@ -40,8 +40,6 @@ after_install = "erpnext.setup.install.after_install"
boot_session = "erpnext.startup.boot.boot_session" boot_session = "erpnext.startup.boot.boot_session"
notification_config = "erpnext.startup.notifications.get_notification_config" notification_config = "erpnext.startup.notifications.get_notification_config"
get_help_messages = "erpnext.utilities.activation.get_help_messages" get_help_messages = "erpnext.utilities.activation.get_help_messages"
get_user_progress_slides = "erpnext.utilities.user_progress.get_user_progress_slides"
update_and_get_user_progress = "erpnext.utilities.user_progress_utils.update_default_domain_actions_and_get_state"
leaderboards = "erpnext.startup.leaderboard.get_leaderboards" leaderboards = "erpnext.startup.leaderboard.get_leaderboards"

View File

@ -1,231 +1,82 @@
{ {
"allow_copy": 0, "creation": "2016-12-20 15:32:25.078334",
"allow_guest_to_view": 0, "doctype": "DocType",
"allow_import": 0, "editable_grid": 1,
"allow_rename": 0, "engine": "InnoDB",
"beta": 0, "field_order": [
"creation": "2016-12-20 15:32:25.078334", "payment_date",
"custom": 0, "principal_amount",
"docstatus": 0, "interest_amount",
"doctype": "DocType", "total_payment",
"document_type": "", "balance_loan_amount",
"editable_grid": 1, "paid"
"engine": "InnoDB", ],
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0, "allow_on_submit": 1,
"allow_on_submit": 0, "columns": 2,
"bold": 0, "fieldname": "payment_date",
"collapsible": 0, "fieldtype": "Date",
"columns": 2, "in_list_view": 1,
"fieldname": "payment_date", "label": "Payment Date"
"fieldtype": "Date", },
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Payment Date",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "columns": 2,
"allow_on_submit": 0, "fieldname": "principal_amount",
"bold": 0, "fieldtype": "Currency",
"collapsible": 0, "in_list_view": 1,
"columns": 2, "label": "Principal Amount",
"fieldname": "principal_amount", "no_copy": 1,
"fieldtype": "Currency", "options": "Company:company:default_currency",
"hidden": 0, "read_only": 1
"ignore_user_permissions": 0, },
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Principal Amount",
"length": 0,
"no_copy": 1,
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "columns": 2,
"allow_on_submit": 0, "fieldname": "interest_amount",
"bold": 0, "fieldtype": "Currency",
"collapsible": 0, "in_list_view": 1,
"columns": 2, "label": "Interest Amount",
"fieldname": "interest_amount", "no_copy": 1,
"fieldtype": "Currency", "options": "Company:company:default_currency",
"hidden": 0, "read_only": 1
"ignore_user_permissions": 0, },
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Interest Amount",
"length": 0,
"no_copy": 1,
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "columns": 2,
"allow_on_submit": 0, "fieldname": "total_payment",
"bold": 0, "fieldtype": "Currency",
"collapsible": 0, "in_list_view": 1,
"columns": 2, "label": "Total Payment",
"fieldname": "total_payment", "options": "Company:company:default_currency",
"fieldtype": "Currency", "read_only": 1
"hidden": 0, },
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Total Payment",
"length": 0,
"no_copy": 0,
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "columns": 2,
"allow_on_submit": 0, "fieldname": "balance_loan_amount",
"bold": 0, "fieldtype": "Currency",
"collapsible": 0, "in_list_view": 1,
"columns": 2, "label": "Balance Loan Amount",
"fieldname": "balance_loan_amount", "no_copy": 1,
"fieldtype": "Currency", "options": "Company:company:default_currency",
"hidden": 0, "read_only": 1
"ignore_user_permissions": 0, },
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Balance Loan Amount",
"length": 0,
"no_copy": 1,
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "default": "0",
"allow_on_submit": 0, "fieldname": "paid",
"bold": 0, "fieldtype": "Check",
"collapsible": 0, "in_list_view": 1,
"columns": 0, "label": "Paid",
"fieldname": "paid", "read_only": 1
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Paid",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
} }
], ],
"has_web_view": 0, "istable": 1,
"hide_heading": 0, "modified": "2019-10-29 11:45:10.694557",
"hide_toolbar": 0, "modified_by": "Administrator",
"idx": 0, "module": "HR",
"image_view": 0, "name": "Repayment Schedule",
"in_create": 0, "owner": "Administrator",
"is_submittable": 0, "permissions": [],
"issingle": 0, "quick_entry": 1,
"istable": 1, "sort_field": "modified",
"max_attachments": 0, "sort_order": "DESC",
"modified": "2018-03-30 17:37:31.834792", "track_changes": 1
"modified_by": "Administrator",
"module": "HR",
"name": "Repayment Schedule",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
} }

View File

@ -9,6 +9,7 @@ from frappe import _
from six import string_types from six import string_types
from erpnext.manufacturing.doctype.bom.bom import get_boms_in_bottom_up_order from erpnext.manufacturing.doctype.bom.bom import get_boms_in_bottom_up_order
from frappe.model.document import Document from frappe.model.document import Document
import click
class BOMUpdateTool(Document): class BOMUpdateTool(Document):
def replace_bom(self): def replace_bom(self):
@ -17,7 +18,8 @@ class BOMUpdateTool(Document):
frappe.cache().delete_key('bom_children') frappe.cache().delete_key('bom_children')
bom_list = self.get_parent_boms(self.new_bom) bom_list = self.get_parent_boms(self.new_bom)
updated_bom = [] updated_bom = []
with click.progressbar(bom_list) as bom_list:
pass
for bom in bom_list: for bom in bom_list:
try: try:
bom_obj = frappe.get_cached_doc('BOM', bom) bom_obj = frappe.get_cached_doc('BOM', bom)

View File

@ -14,7 +14,7 @@ def execute(filters=None):
def get_data(filters, data): def get_data(filters, data):
get_exploded_items(filters.bom, data) get_exploded_items(filters.bom, data)
def get_exploded_items(bom, data, indent=0): def get_exploded_items(bom, data, indent=0, qty=1):
exploded_items = frappe.get_all("BOM Item", exploded_items = frappe.get_all("BOM Item",
filters={"parent": bom}, filters={"parent": bom},
fields= ['qty','bom_no','qty','scrap','item_code','item_name','description','uom']) fields= ['qty','bom_no','qty','scrap','item_code','item_name','description','uom'])
@ -26,13 +26,13 @@ def get_exploded_items(bom, data, indent=0):
'item_name': item.item_name, 'item_name': item.item_name,
'indent': indent, 'indent': indent,
'bom': item.bom_no, 'bom': item.bom_no,
'qty': item.qty, 'qty': item.qty * qty,
'uom': item.uom, 'uom': item.uom,
'description': item.description, 'description': item.description,
'scrap': item.scrap 'scrap': item.scrap
}) })
if item.bom_no: if item.bom_no:
get_exploded_items(item.bom_no, data, indent=indent+1) get_exploded_items(item.bom_no, data, indent=indent+1, qty=item.qty)
def get_columns(): def get_columns():
return [ return [

View File

@ -5,6 +5,9 @@ from frappe import _
def execute(): def execute():
"""Add setup progress actions""" """Add setup progress actions"""
if not frappe.db.exists('DocType', 'Setup Progress') or not frappe.db.exists('DocType', 'Setup Progress Action'):
return
frappe.reload_doc("setup", "doctype", "setup_progress") frappe.reload_doc("setup", "doctype", "setup_progress")
frappe.reload_doc("setup", "doctype", "setup_progress_action") frappe.reload_doc("setup", "doctype", "setup_progress_action")

View File

@ -5,7 +5,7 @@ from __future__ import unicode_literals
import frappe import frappe
import unittest import unittest
from frappe.tests.test_website import set_request from frappe.utils import set_request
from frappe.website.render import render from frappe.website.render import render
class TestHomepage(unittest.TestCase): class TestHomepage(unittest.TestCase):

View File

@ -6,7 +6,7 @@ from __future__ import unicode_literals
import frappe import frappe
import unittest import unittest
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from frappe.tests.test_website import set_request from frappe.utils import set_request
from frappe.website.render import render from frappe.website.render import render
class TestHomepageSection(unittest.TestCase): class TestHomepageSection(unittest.TestCase):

View File

@ -2,7 +2,7 @@ from __future__ import unicode_literals
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
import frappe, unittest import frappe, unittest
from frappe.tests.test_website import set_request, get_html_for_route from frappe.utils import set_request, get_html_for_route
from frappe.website.render import render from frappe.website.render import render
from erpnext.portal.product_configurator.utils import get_products_for_website from erpnext.portal.product_configurator.utils import get_products_for_website
from erpnext.stock.doctype.item.test_item import make_item_variant from erpnext.stock.doctype.item.test_item import make_item_variant

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@ -426,7 +426,7 @@ body[data-route="pos"] {
.collapse-btn { .collapse-btn {
cursor: pointer; cursor: pointer;
} }
@media (max-width: @screen-xs) { @media (max-width: @screen-xs) {
.page-actions { .page-actions {
max-width: 110px; max-width: 110px;

View File

@ -3,6 +3,26 @@
frappe.ui.form.on('GST HSN Code', { frappe.ui.form.on('GST HSN Code', {
refresh: function(frm) { refresh: function(frm) {
if(! frm.doc.__islocal && frm.doc.taxes.length){
frm.add_custom_button(__('Update Taxes for Items'), function(){
frappe.confirm(
'Are you sure? It will overwrite taxes for all items with HSN Code <b>'+frm.doc.name+'</b>.',
function(){
frappe.call({
args:{
taxes: frm.doc.taxes,
hsn_code: frm.doc.name
},
method: 'erpnext.regional.doctype.gst_hsn_code.gst_hsn_code.update_taxes_in_item_master',
callback: function(r) {
if(r.message){
frappe.show_alert(__('Item taxes updated'));
}
}
});
}
);
});
}
} }
}); });

View File

@ -1,104 +1,46 @@
{ {
"allow_copy": 0, "autoname": "field:hsn_code",
"allow_guest_to_view": 0, "creation": "2017-06-21 10:48:56.422086",
"allow_import": 0, "doctype": "DocType",
"allow_rename": 0, "editable_grid": 1,
"autoname": "field:hsn_code", "engine": "InnoDB",
"beta": 0, "field_order": [
"creation": "2017-06-21 10:48:56.422086", "hsn_code",
"custom": 0, "description",
"docstatus": 0, "taxes"
"doctype": "DocType", ],
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0, "fieldname": "hsn_code",
"allow_on_submit": 0, "fieldtype": "Data",
"bold": 0, "in_list_view": 1,
"collapsible": 0, "label": "HSN Code",
"columns": 0, "reqd": 1,
"fieldname": "hsn_code", "unique": 1
"fieldtype": "Data", },
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "HSN Code",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "description",
"allow_on_submit": 0, "fieldtype": "Small Text",
"bold": 0, "in_list_view": 1,
"collapsible": 0, "label": "Description"
"columns": 0, },
"fieldname": "description", {
"fieldtype": "Small Text", "fieldname": "taxes",
"hidden": 0, "fieldtype": "Table",
"ignore_user_permissions": 0, "label": "Taxes",
"ignore_xss_filter": 0, "options": "Item Tax"
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Description",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
} }
], ],
"has_web_view": 0, "modified": "2019-11-01 11:18:59.556931",
"hide_heading": 0, "modified_by": "Administrator",
"hide_toolbar": 0, "module": "Regional",
"idx": 0, "name": "GST HSN Code",
"image_view": 0, "owner": "Administrator",
"in_create": 0, "permissions": [],
"is_submittable": 0, "quick_entry": 1,
"issingle": 0, "search_fields": "hsn_code, description",
"istable": 0, "sort_field": "modified",
"max_attachments": 0, "sort_order": "DESC",
"modified": "2017-09-29 14:38:52.220743", "title_field": "hsn_code",
"modified_by": "Administrator", "track_changes": 1
"module": "Regional",
"name": "GST HSN Code",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"search_fields": "hsn_code, description",
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "hsn_code",
"track_changes": 1,
"track_seen": 0
} }

View File

@ -8,3 +8,22 @@ from frappe.model.document import Document
class GSTHSNCode(Document): class GSTHSNCode(Document):
pass pass
@frappe.whitelist()
def update_taxes_in_item_master(taxes, hsn_code):
items = frappe.get_list("Item", filters={
'gst_hsn_code': hsn_code
})
taxes = frappe.parse_json(taxes)
frappe.enqueue(update_item_document, items=items, taxes=taxes)
return 1
def update_item_document(items, taxes):
for item in items:
item_to_be_updated=frappe.get_doc("Item", item.name)
item_to_be_updated.taxes = []
for tax in taxes:
tax = frappe._dict(tax)
item_to_be_updated.append("taxes", {'item_tax_template': tax.item_tax_template, 'tax_category': tax.tax_category})
item_to_be_updated.save()

View File

@ -10,17 +10,26 @@ Provide a report and downloadable CSV according to the German DATEV format.
from __future__ import unicode_literals from __future__ import unicode_literals
import datetime import datetime
import json import json
import zlib
import zipfile
import six
from six import BytesIO
from six import string_types from six import string_types
import frappe import frappe
from frappe import _ from frappe import _
import pandas as pd import pandas as pd
from .datev_constants import DataCategory
from .datev_constants import Transactions
from .datev_constants import DebtorsCreditors
from .datev_constants import AccountNames
from .datev_constants import QUERY_REPORT_COLUMNS
def execute(filters=None): def execute(filters=None):
"""Entry point for frappe.""" """Entry point for frappe."""
validate(filters) validate(filters)
result = get_gl_entries(filters, as_dict=0) result = get_transactions(filters, as_dict=0)
columns = get_columns() columns = QUERY_REPORT_COLUMNS
return columns, result return columns, result
@ -41,65 +50,8 @@ def validate(filters):
except frappe.DoesNotExistError: except frappe.DoesNotExistError:
frappe.throw(_('Please create <b>DATEV Settings</b> for Company <b>{}</b>.').format(filters.get('company'))) frappe.throw(_('Please create <b>DATEV Settings</b> for Company <b>{}</b>.').format(filters.get('company')))
def get_columns():
"""Return the list of columns that will be shown in query report."""
columns = [
{
"label": "Umsatz (ohne Soll/Haben-Kz)",
"fieldname": "Umsatz (ohne Soll/Haben-Kz)",
"fieldtype": "Currency",
},
{
"label": "Soll/Haben-Kennzeichen",
"fieldname": "Soll/Haben-Kennzeichen",
"fieldtype": "Data",
},
{
"label": "Kontonummer",
"fieldname": "Kontonummer",
"fieldtype": "Data",
},
{
"label": "Gegenkonto (ohne BU-Schlüssel)",
"fieldname": "Gegenkonto (ohne BU-Schlüssel)",
"fieldtype": "Data",
},
{
"label": "Belegdatum",
"fieldname": "Belegdatum",
"fieldtype": "Date",
},
{
"label": "Buchungstext",
"fieldname": "Buchungstext",
"fieldtype": "Text",
},
{
"label": "Beleginfo - Art 1",
"fieldname": "Beleginfo - Art 1",
"fieldtype": "Data",
},
{
"label": "Beleginfo - Inhalt 1",
"fieldname": "Beleginfo - Inhalt 1",
"fieldtype": "Data",
},
{
"label": "Beleginfo - Art 2",
"fieldname": "Beleginfo - Art 2",
"fieldtype": "Data",
},
{
"label": "Beleginfo - Inhalt 2",
"fieldname": "Beleginfo - Inhalt 2",
"fieldtype": "Data",
}
]
return columns def get_transactions(filters, as_dict=1):
def get_gl_entries(filters, as_dict):
""" """
Get a list of accounting entries. Get a list of accounting entries.
@ -111,7 +63,7 @@ def get_gl_entries(filters, as_dict):
as_dict -- return as list of dicts [0,1] as_dict -- return as list of dicts [0,1]
""" """
gl_entries = frappe.db.sql(""" gl_entries = frappe.db.sql("""
select SELECT
/* either debit or credit amount; always positive */ /* either debit or credit amount; always positive */
case gl.debit when 0 then gl.credit else gl.debit end as 'Umsatz (ohne Soll/Haben-Kz)', case gl.debit when 0 then gl.credit else gl.debit end as 'Umsatz (ohne Soll/Haben-Kz)',
@ -132,7 +84,7 @@ def get_gl_entries(filters, as_dict):
gl.against_voucher_type as 'Beleginfo - Art 2', gl.against_voucher_type as 'Beleginfo - Art 2',
gl.against_voucher as 'Beleginfo - Inhalt 2' gl.against_voucher as 'Beleginfo - Inhalt 2'
from `tabGL Entry` gl FROM `tabGL Entry` gl
/* Statistisches Konto (Debitoren/Kreditoren) */ /* Statistisches Konto (Debitoren/Kreditoren) */
left join `tabParty Account` pa left join `tabParty Account` pa
@ -155,15 +107,127 @@ def get_gl_entries(filters, as_dict):
left join `tabAccount` acc_against_pa left join `tabAccount` acc_against_pa
on pa.account = acc_against_pa.name on pa.account = acc_against_pa.name
where gl.company = %(company)s WHERE gl.company = %(company)s
and DATE(gl.posting_date) >= %(from_date)s AND DATE(gl.posting_date) >= %(from_date)s
and DATE(gl.posting_date) <= %(to_date)s AND DATE(gl.posting_date) <= %(to_date)s
order by 'Belegdatum', gl.voucher_no""", filters, as_dict=as_dict) ORDER BY 'Belegdatum', gl.voucher_no""", filters, as_dict=as_dict, as_utf8=1)
return gl_entries return gl_entries
def get_datev_csv(data, filters): def get_customers(filters):
"""
Get a list of Customers.
Arguments:
filters -- dict of filters to be passed to the sql query
"""
return frappe.db.sql("""
SELECT
acc.account_number as 'Konto',
cus.customer_name as 'Name (Adressatentyp Unternehmen)',
case cus.customer_type when 'Individual' then 1 when 'Company' then 2 else 0 end as 'Adressatentyp',
adr.address_line1 as 'Straße',
adr.pincode as 'Postleitzahl',
adr.city as 'Ort',
UPPER(country.code) as 'Land',
adr.address_line2 as 'Adresszusatz',
con.email_id as 'E-Mail',
coalesce(con.mobile_no, con.phone) as 'Telefon',
cus.website as 'Internet',
cus.tax_id as 'Steuernummer',
ccl.credit_limit as 'Kreditlimit (Debitor)'
FROM `tabParty Account` par
left join `tabAccount` acc
on acc.name = par.account
left join `tabCustomer` cus
on cus.name = par.parent
left join `tabAddress` adr
on adr.name = cus.customer_primary_address
left join `tabCountry` country
on country.name = adr.country
left join `tabContact` con
on con.name = cus.customer_primary_contact
left join `tabCustomer Credit Limit` ccl
on ccl.parent = cus.name
and ccl.company = par.company
WHERE par.company = %(company)s
AND par.parenttype = 'Customer'""", filters, as_dict=1, as_utf8=1)
def get_suppliers(filters):
"""
Get a list of Suppliers.
Arguments:
filters -- dict of filters to be passed to the sql query
"""
return frappe.db.sql("""
SELECT
acc.account_number as 'Konto',
sup.supplier_name as 'Name (Adressatentyp Unternehmen)',
case sup.supplier_type when 'Individual' then '1' when 'Company' then '2' else '0' end as 'Adressatentyp',
adr.address_line1 as 'Straße',
adr.pincode as 'Postleitzahl',
adr.city as 'Ort',
UPPER(country.code) as 'Land',
adr.address_line2 as 'Adresszusatz',
con.email_id as 'E-Mail',
coalesce(con.mobile_no, con.phone) as 'Telefon',
sup.website as 'Internet',
sup.tax_id as 'Steuernummer',
case sup.on_hold when 1 then sup.release_date else null end as 'Zahlungssperre bis'
FROM `tabParty Account` par
left join `tabAccount` acc
on acc.name = par.account
left join `tabSupplier` sup
on sup.name = par.parent
left join `tabDynamic Link` dyn_adr
on dyn_adr.link_name = sup.name
and dyn_adr.link_doctype = 'Supplier'
and dyn_adr.parenttype = 'Address'
left join `tabAddress` adr
on adr.name = dyn_adr.parent
and adr.is_primary_address = '1'
left join `tabCountry` country
on country.name = adr.country
left join `tabDynamic Link` dyn_con
on dyn_con.link_name = sup.name
and dyn_con.link_doctype = 'Supplier'
and dyn_con.parenttype = 'Contact'
left join `tabContact` con
on con.name = dyn_con.parent
and con.is_primary_contact = '1'
WHERE par.company = %(company)s
AND par.parenttype = 'Supplier'""", filters, as_dict=1, as_utf8=1)
def get_account_names(filters):
return frappe.get_list("Account",
fields=["account_number as Konto", "name as Kontenbeschriftung"],
filters={"company": filters.get("company"), "is_group": "0"})
def get_datev_csv(data, filters, csv_class):
""" """
Fill in missing columns and return a CSV in DATEV Format. Fill in missing columns and return a CSV in DATEV Format.
@ -174,7 +238,46 @@ def get_datev_csv(data, filters):
Arguments: Arguments:
data -- array of dictionaries data -- array of dictionaries
filters -- dict filters -- dict
csv_class -- defines DATA_CATEGORY, FORMAT_NAME and COLUMNS
""" """
header = get_header(filters, csv_class)
empty_df = pd.DataFrame(columns=csv_class.COLUMNS)
data_df = pd.DataFrame.from_records(data)
result = empty_df.append(data_df, sort=True)
if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS:
result['Belegdatum'] = pd.to_datetime(result['Belegdatum'])
if csv_class.DATA_CATEGORY == DataCategory.ACCOUNT_NAMES:
result['Sprach-ID'] = 'de-DE'
header = ';'.join(header).encode('latin_1')
data = result.to_csv(
# Reason for str(';'): https://github.com/pandas-dev/pandas/issues/6035
sep=str(';'),
# European decimal seperator
decimal=',',
# Windows "ANSI" encoding
encoding='latin_1',
# format date as DDMM
date_format='%d%m',
# Windows line terminator
line_terminator='\r\n',
# Do not number rows
index=False,
# Use all columns defined above
columns=csv_class.COLUMNS
)
if not six.PY2:
data = data.encode('latin_1')
return header + b'\r\n' + data
def get_header(filters, csv_class):
header = [ header = [
# A = DATEV format # A = DATEV format
# DTVF = created by DATEV software, # DTVF = created by DATEV software,
@ -185,18 +288,8 @@ def get_datev_csv(data, filters):
# 510 = 5.10, # 510 = 5.10,
# 720 = 7.20 # 720 = 7.20
"510", "510",
# C = Data category csv_class.DATA_CATEGORY,
# 21 = Transaction batch (Buchungsstapel), csv_class.FORMAT_NAME,
# 67 = Buchungstextkonstanten,
# 16 = Debitors/Creditors,
# 20 = Account names (Kontenbeschriftungen)
"21",
# D = Format name
# Buchungsstapel,
# Buchungstextkonstanten,
# Debitoren/Kreditoren,
# Kontenbeschriftungen
"Buchungsstapel",
# E = Format version (regarding format name) # E = Format version (regarding format name)
"", "",
# F = Generated on # F = Generated on
@ -224,16 +317,17 @@ def get_datev_csv(data, filters):
# P = Transaction batch end date (YYYYMMDD) # P = Transaction batch end date (YYYYMMDD)
frappe.utils.formatdate(filters.get('to_date'), "yyyyMMdd"), frappe.utils.formatdate(filters.get('to_date'), "yyyyMMdd"),
# Q = Description (for example, "January - February 2019 Transactions") # Q = Description (for example, "January - February 2019 Transactions")
"{} - {} Buchungsstapel".format( "{} - {} {}".format(
frappe.utils.formatdate(filters.get('from_date'), "MMMM yyyy"), frappe.utils.formatdate(filters.get('from_date'), "MMMM yyyy"),
frappe.utils.formatdate(filters.get('to_date'), "MMMM yyyy") frappe.utils.formatdate(filters.get('to_date'), "MMMM yyyy"),
csv_class.FORMAT_NAME
), ),
# R = Diktatkürzel # R = Diktatkürzel
"", "",
# S = Buchungstyp # S = Buchungstyp
# 1 = Transaction batch (Buchungsstapel), # 1 = Transaction batch (Buchungsstapel),
# 2 = Annual financial statement (Jahresabschluss) # 2 = Annual financial statement (Jahresabschluss)
"1", "1" if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS else "",
# T = Rechnungslegungszweck # T = Rechnungslegungszweck
"", "",
# U = Festschreibung # U = Festschreibung
@ -241,185 +335,8 @@ def get_datev_csv(data, filters):
# V = Kontoführungs-Währungskennzeichen des Geldkontos # V = Kontoführungs-Währungskennzeichen des Geldkontos
frappe.get_value("Company", filters.get("company"), "default_currency") frappe.get_value("Company", filters.get("company"), "default_currency")
] ]
columns = [ return header
# All possible columns must tbe listed here, because DATEV requires them to
# be present in the CSV.
# ---
# Umsatz
"Umsatz (ohne Soll/Haben-Kz)",
"Soll/Haben-Kennzeichen",
"WKZ Umsatz",
"Kurs",
"Basis-Umsatz",
"WKZ Basis-Umsatz",
# Konto/Gegenkonto
"Kontonummer",
"Gegenkonto (ohne BU-Schlüssel)",
"BU-Schlüssel",
# Datum
"Belegdatum",
# Belegfelder
"Belegfeld 1",
"Belegfeld 2",
# Weitere Felder
"Skonto",
"Buchungstext",
# OPOS-Informationen
"Postensperre",
"Diverse Adressnummer",
"Geschäftspartnerbank",
"Sachverhalt",
"Zinssperre",
# Digitaler Beleg
"Beleglink",
# Beleginfo
"Beleginfo - Art 1",
"Beleginfo - Inhalt 1",
"Beleginfo - Art 2",
"Beleginfo - Inhalt 2",
"Beleginfo - Art 3",
"Beleginfo - Inhalt 3",
"Beleginfo - Art 4",
"Beleginfo - Inhalt 4",
"Beleginfo - Art 5",
"Beleginfo - Inhalt 5",
"Beleginfo - Art 6",
"Beleginfo - Inhalt 6",
"Beleginfo - Art 7",
"Beleginfo - Inhalt 7",
"Beleginfo - Art 8",
"Beleginfo - Inhalt 8",
# Kostenrechnung
"Kost 1 - Kostenstelle",
"Kost 2 - Kostenstelle",
"Kost-Menge",
# Steuerrechnung
"EU-Land u. UStID",
"EU-Steuersatz",
"Abw. Versteuerungsart",
# L+L Sachverhalt
"Sachverhalt L+L",
"Funktionsergänzung L+L",
# Funktion Steuerschlüssel 49
"BU 49 Hauptfunktionstyp",
"BU 49 Hauptfunktionsnummer",
"BU 49 Funktionsergänzung",
# Zusatzinformationen
"Zusatzinformation - Art 1",
"Zusatzinformation - Inhalt 1",
"Zusatzinformation - Art 2",
"Zusatzinformation - Inhalt 2",
"Zusatzinformation - Art 3",
"Zusatzinformation - Inhalt 3",
"Zusatzinformation - Art 4",
"Zusatzinformation - Inhalt 4",
"Zusatzinformation - Art 5",
"Zusatzinformation - Inhalt 5",
"Zusatzinformation - Art 6",
"Zusatzinformation - Inhalt 6",
"Zusatzinformation - Art 7",
"Zusatzinformation - Inhalt 7",
"Zusatzinformation - Art 8",
"Zusatzinformation - Inhalt 8",
"Zusatzinformation - Art 9",
"Zusatzinformation - Inhalt 9",
"Zusatzinformation - Art 10",
"Zusatzinformation - Inhalt 10",
"Zusatzinformation - Art 11",
"Zusatzinformation - Inhalt 11",
"Zusatzinformation - Art 12",
"Zusatzinformation - Inhalt 12",
"Zusatzinformation - Art 13",
"Zusatzinformation - Inhalt 13",
"Zusatzinformation - Art 14",
"Zusatzinformation - Inhalt 14",
"Zusatzinformation - Art 15",
"Zusatzinformation - Inhalt 15",
"Zusatzinformation - Art 16",
"Zusatzinformation - Inhalt 16",
"Zusatzinformation - Art 17",
"Zusatzinformation - Inhalt 17",
"Zusatzinformation - Art 18",
"Zusatzinformation - Inhalt 18",
"Zusatzinformation - Art 19",
"Zusatzinformation - Inhalt 19",
"Zusatzinformation - Art 20",
"Zusatzinformation - Inhalt 20",
# Mengenfelder LuF
"Stück",
"Gewicht",
# Forderungsart
"Zahlweise",
"Forderungsart",
"Veranlagungsjahr",
"Zugeordnete Fälligkeit",
# Weitere Felder
"Skontotyp",
# Anzahlungen
"Auftragsnummer",
"Buchungstyp",
"USt-Schlüssel (Anzahlungen)",
"EU-Land (Anzahlungen)",
"Sachverhalt L+L (Anzahlungen)",
"EU-Steuersatz (Anzahlungen)",
"Erlöskonto (Anzahlungen)",
# Stapelinformationen
"Herkunft-Kz",
# Technische Identifikation
"Buchungs GUID",
# Kostenrechnung
"Kost-Datum",
# OPOS-Informationen
"SEPA-Mandatsreferenz",
"Skontosperre",
# Gesellschafter und Sonderbilanzsachverhalt
"Gesellschaftername",
"Beteiligtennummer",
"Identifikationsnummer",
"Zeichnernummer",
# OPOS-Informationen
"Postensperre bis",
# Gesellschafter und Sonderbilanzsachverhalt
"Bezeichnung SoBil-Sachverhalt",
"Kennzeichen SoBil-Buchung",
# Stapelinformationen
"Festschreibung",
# Datum
"Leistungsdatum",
"Datum Zuord. Steuerperiode",
# OPOS-Informationen
"Fälligkeit",
# Konto/Gegenkonto
"Generalumkehr (GU)",
# Steuersatz für Steuerschlüssel
"Steuersatz",
"Land"
]
empty_df = pd.DataFrame(columns=columns)
data_df = pd.DataFrame.from_records(data)
result = empty_df.append(data_df)
result['Belegdatum'] = pd.to_datetime(result['Belegdatum'])
header = ';'.join(header).encode('latin_1')
data = result.to_csv(
sep=b';',
# European decimal seperator
decimal=',',
# Windows "ANSI" encoding
encoding='latin_1',
# format date as DDMM
date_format='%d%m',
# Windows line terminator
line_terminator=b'\r\n',
# Do not number rows
index=False,
# Use all columns defined above
columns=columns
)
return header + b'\r\n' + data
@frappe.whitelist() @frappe.whitelist()
def download_datev_csv(filters=None): def download_datev_csv(filters=None):
@ -438,8 +355,31 @@ def download_datev_csv(filters=None):
filters = json.loads(filters) filters = json.loads(filters)
validate(filters) validate(filters)
data = get_gl_entries(filters, as_dict=1)
frappe.response['result'] = get_datev_csv(data, filters) # This is where my zip will be written
frappe.response['doctype'] = 'EXTF_Buchungsstapel' zip_buffer = BytesIO()
frappe.response['type'] = 'csv' # This is my zip file
datev_zip = zipfile.ZipFile(zip_buffer, mode='w', compression=zipfile.ZIP_DEFLATED)
transactions = get_transactions(filters)
transactions_csv = get_datev_csv(transactions, filters, csv_class=Transactions)
datev_zip.writestr('EXTF_Buchungsstapel.csv', transactions_csv)
account_names = get_account_names(filters)
account_names_csv = get_datev_csv(account_names, filters, csv_class=AccountNames)
datev_zip.writestr('EXTF_Kontenbeschriftungen.csv', account_names_csv)
customers = get_customers(filters)
customers_csv = get_datev_csv(customers, filters, csv_class=DebtorsCreditors)
datev_zip.writestr('EXTF_Kunden.csv', customers_csv)
suppliers = get_suppliers(filters)
suppliers_csv = get_datev_csv(suppliers, filters, csv_class=DebtorsCreditors)
datev_zip.writestr('EXTF_Lieferanten.csv', suppliers_csv)
# You must call close() before exiting your program or essential records will not be written.
datev_zip.close()
frappe.response['filecontent'] = zip_buffer.getvalue()
frappe.response['filename'] = 'DATEV.zip'
frappe.response['type'] = 'binary'

View File

@ -0,0 +1,512 @@
# coding: utf-8
"""Constants used in datev.py."""
TRANSACTION_COLUMNS = [
# All possible columns must tbe listed here, because DATEV requires them to
# be present in the CSV.
# ---
# Umsatz
"Umsatz (ohne Soll/Haben-Kz)",
"Soll/Haben-Kennzeichen",
"WKZ Umsatz",
"Kurs",
"Basis-Umsatz",
"WKZ Basis-Umsatz",
# Konto/Gegenkonto
"Kontonummer",
"Gegenkonto (ohne BU-Schlüssel)",
"BU-Schlüssel",
# Datum
"Belegdatum",
# Belegfelder
"Belegfeld 1",
"Belegfeld 2",
# Weitere Felder
"Skonto",
"Buchungstext",
# OPOS-Informationen
"Postensperre",
"Diverse Adressnummer",
"Geschäftspartnerbank",
"Sachverhalt",
"Zinssperre",
# Digitaler Beleg
"Beleglink",
# Beleginfo
"Beleginfo - Art 1",
"Beleginfo - Inhalt 1",
"Beleginfo - Art 2",
"Beleginfo - Inhalt 2",
"Beleginfo - Art 3",
"Beleginfo - Inhalt 3",
"Beleginfo - Art 4",
"Beleginfo - Inhalt 4",
"Beleginfo - Art 5",
"Beleginfo - Inhalt 5",
"Beleginfo - Art 6",
"Beleginfo - Inhalt 6",
"Beleginfo - Art 7",
"Beleginfo - Inhalt 7",
"Beleginfo - Art 8",
"Beleginfo - Inhalt 8",
# Kostenrechnung
"Kost 1 - Kostenstelle",
"Kost 2 - Kostenstelle",
"Kost-Menge",
# Steuerrechnung
"EU-Land u. UStID",
"EU-Steuersatz",
"Abw. Versteuerungsart",
# L+L Sachverhalt
"Sachverhalt L+L",
"Funktionsergänzung L+L",
# Funktion Steuerschlüssel 49
"BU 49 Hauptfunktionstyp",
"BU 49 Hauptfunktionsnummer",
"BU 49 Funktionsergänzung",
# Zusatzinformationen
"Zusatzinformation - Art 1",
"Zusatzinformation - Inhalt 1",
"Zusatzinformation - Art 2",
"Zusatzinformation - Inhalt 2",
"Zusatzinformation - Art 3",
"Zusatzinformation - Inhalt 3",
"Zusatzinformation - Art 4",
"Zusatzinformation - Inhalt 4",
"Zusatzinformation - Art 5",
"Zusatzinformation - Inhalt 5",
"Zusatzinformation - Art 6",
"Zusatzinformation - Inhalt 6",
"Zusatzinformation - Art 7",
"Zusatzinformation - Inhalt 7",
"Zusatzinformation - Art 8",
"Zusatzinformation - Inhalt 8",
"Zusatzinformation - Art 9",
"Zusatzinformation - Inhalt 9",
"Zusatzinformation - Art 10",
"Zusatzinformation - Inhalt 10",
"Zusatzinformation - Art 11",
"Zusatzinformation - Inhalt 11",
"Zusatzinformation - Art 12",
"Zusatzinformation - Inhalt 12",
"Zusatzinformation - Art 13",
"Zusatzinformation - Inhalt 13",
"Zusatzinformation - Art 14",
"Zusatzinformation - Inhalt 14",
"Zusatzinformation - Art 15",
"Zusatzinformation - Inhalt 15",
"Zusatzinformation - Art 16",
"Zusatzinformation - Inhalt 16",
"Zusatzinformation - Art 17",
"Zusatzinformation - Inhalt 17",
"Zusatzinformation - Art 18",
"Zusatzinformation - Inhalt 18",
"Zusatzinformation - Art 19",
"Zusatzinformation - Inhalt 19",
"Zusatzinformation - Art 20",
"Zusatzinformation - Inhalt 20",
# Mengenfelder LuF
"Stück",
"Gewicht",
# Forderungsart
"Zahlweise",
"Forderungsart",
"Veranlagungsjahr",
"Zugeordnete Fälligkeit",
# Weitere Felder
"Skontotyp",
# Anzahlungen
"Auftragsnummer",
"Buchungstyp",
"USt-Schlüssel (Anzahlungen)",
"EU-Land (Anzahlungen)",
"Sachverhalt L+L (Anzahlungen)",
"EU-Steuersatz (Anzahlungen)",
"Erlöskonto (Anzahlungen)",
# Stapelinformationen
"Herkunft-Kz",
# Technische Identifikation
"Buchungs GUID",
# Kostenrechnung
"Kost-Datum",
# OPOS-Informationen
"SEPA-Mandatsreferenz",
"Skontosperre",
# Gesellschafter und Sonderbilanzsachverhalt
"Gesellschaftername",
"Beteiligtennummer",
"Identifikationsnummer",
"Zeichnernummer",
# OPOS-Informationen
"Postensperre bis",
# Gesellschafter und Sonderbilanzsachverhalt
"Bezeichnung SoBil-Sachverhalt",
"Kennzeichen SoBil-Buchung",
# Stapelinformationen
"Festschreibung",
# Datum
"Leistungsdatum",
"Datum Zuord. Steuerperiode",
# OPOS-Informationen
"Fälligkeit",
# Konto/Gegenkonto
"Generalumkehr (GU)",
# Steuersatz für Steuerschlüssel
"Steuersatz",
"Land"
]
DEBTOR_CREDITOR_COLUMNS = [
# All possible columns must tbe listed here, because DATEV requires them to
# be present in the CSV.
# Columns "Leerfeld" have been replaced with "Leerfeld #" to not confuse pandas
# ---
"Konto",
"Name (Adressatentyp Unternehmen)",
"Unternehmensgegenstand",
"Name (Adressatentyp natürl. Person)",
"Vorname (Adressatentyp natürl. Person)",
"Name (Adressatentyp keine Angabe)",
"Adressatentyp",
"Kurzbezeichnung",
"EU-Land",
"EU-USt-IdNr.",
"Anrede",
"Titel/Akad. Grad",
"Adelstitel",
"Namensvorsatz",
"Adressart",
"Straße",
"Postfach",
"Postleitzahl",
"Ort",
"Land",
"Versandzusatz",
"Adresszusatz",
"Abweichende Anrede",
"Abw. Zustellbezeichnung 1",
"Abw. Zustellbezeichnung 2",
"Kennz. Korrespondenzadresse",
"Adresse gültig von",
"Adresse gültig bis",
"Telefon",
"Bemerkung (Telefon)",
"Telefon Geschäftsleitung",
"Bemerkung (Telefon GL)",
"E-Mail",
"Bemerkung (E-Mail)",
"Internet",
"Bemerkung (Internet)",
"Fax",
"Bemerkung (Fax)",
"Sonstige",
"Bemerkung (Sonstige)",
"Bankleitzahl 1",
"Bankbezeichnung 1",
"Bankkonto-Nummer 1",
"Länderkennzeichen 1",
"IBAN 1",
"Leerfeld 1",
"SWIFT-Code 1",
"Abw. Kontoinhaber 1",
"Kennz. Haupt-Bankverb. 1",
"Bankverb. 1 Gültig von",
"Bankverb. 1 Gültig bis",
"Bankleitzahl 2",
"Bankbezeichnung 2",
"Bankkonto-Nummer 2",
"Länderkennzeichen 2",
"IBAN 2",
"Leerfeld 2",
"SWIFT-Code 2",
"Abw. Kontoinhaber 2",
"Kennz. Haupt-Bankverb. 2",
"Bankverb. 2 gültig von",
"Bankverb. 2 gültig bis",
"Bankleitzahl 3",
"Bankbezeichnung 3",
"Bankkonto-Nummer 3",
"Länderkennzeichen 3",
"IBAN 3",
"Leerfeld 3",
"SWIFT-Code 3",
"Abw. Kontoinhaber 3",
"Kennz. Haupt-Bankverb. 3",
"Bankverb. 3 gültig von",
"Bankverb. 3 gültig bis",
"Bankleitzahl 4",
"Bankbezeichnung 4",
"Bankkonto-Nummer 4",
"Länderkennzeichen 4",
"IBAN 4",
"Leerfeld 4",
"SWIFT-Code 4",
"Abw. Kontoinhaber 4",
"Kennz. Haupt-Bankverb. 4",
"Bankverb. 4 Gültig von",
"Bankverb. 4 Gültig bis",
"Bankleitzahl 5",
"Bankbezeichnung 5",
"Bankkonto-Nummer 5",
"Länderkennzeichen 5",
"IBAN 5",
"Leerfeld 5",
"SWIFT-Code 5",
"Abw. Kontoinhaber 5",
"Kennz. Haupt-Bankverb. 5",
"Bankverb. 5 gültig von",
"Bankverb. 5 gültig bis",
"Leerfeld 6",
"Briefanrede",
"Grußformel",
"Kundennummer",
"Steuernummer",
"Sprache",
"Ansprechpartner",
"Vertreter",
"Sachbearbeiter",
"Diverse-Konto",
"Ausgabeziel",
"Währungssteuerung",
"Kreditlimit (Debitor)",
"Zahlungsbedingung",
"Fälligkeit in Tagen (Debitor)",
"Skonto in Prozent (Debitor)",
"Kreditoren-Ziel 1 (Tage)",
"Kreditoren-Skonto 1 (%)",
"Kreditoren-Ziel 2 (Tage)",
"Kreditoren-Skonto 2 (%)",
"Kreditoren-Ziel 3 Brutto (Tage)",
"Kreditoren-Ziel 4 (Tage)",
"Kreditoren-Skonto 4 (%)",
"Kreditoren-Ziel 5 (Tage)",
"Kreditoren-Skonto 5 (%)",
"Mahnung",
"Kontoauszug",
"Mahntext 1",
"Mahntext 2",
"Mahntext 3",
"Kontoauszugstext",
"Mahnlimit Betrag",
"Mahnlimit %",
"Zinsberechnung",
"Mahnzinssatz 1",
"Mahnzinssatz 2",
"Mahnzinssatz 3",
"Lastschrift",
"Verfahren",
"Mandantenbank",
"Zahlungsträger",
"Indiv. Feld 1",
"Indiv. Feld 2",
"Indiv. Feld 3",
"Indiv. Feld 4",
"Indiv. Feld 5",
"Indiv. Feld 6",
"Indiv. Feld 7",
"Indiv. Feld 8",
"Indiv. Feld 9",
"Indiv. Feld 10",
"Indiv. Feld 11",
"Indiv. Feld 12",
"Indiv. Feld 13",
"Indiv. Feld 14",
"Indiv. Feld 15",
"Abweichende Anrede (Rechnungsadresse)",
"Adressart (Rechnungsadresse)",
"Straße (Rechnungsadresse)",
"Postfach (Rechnungsadresse)",
"Postleitzahl (Rechnungsadresse)",
"Ort (Rechnungsadresse)",
"Land (Rechnungsadresse)",
"Versandzusatz (Rechnungsadresse)",
"Adresszusatz (Rechnungsadresse)",
"Abw. Zustellbezeichnung 1 (Rechnungsadresse)",
"Abw. Zustellbezeichnung 2 (Rechnungsadresse)",
"Adresse Gültig von (Rechnungsadresse)",
"Adresse Gültig bis (Rechnungsadresse)",
"Bankleitzahl 6",
"Bankbezeichnung 6",
"Bankkonto-Nummer 6",
"Länderkennzeichen 6",
"IBAN 6",
"Leerfeld 7",
"SWIFT-Code 6",
"Abw. Kontoinhaber 6",
"Kennz. Haupt-Bankverb. 6",
"Bankverb 6 gültig von",
"Bankverb 6 gültig bis",
"Bankleitzahl 7",
"Bankbezeichnung 7",
"Bankkonto-Nummer 7",
"Länderkennzeichen 7",
"IBAN 7",
"Leerfeld 8",
"SWIFT-Code 7",
"Abw. Kontoinhaber 7",
"Kennz. Haupt-Bankverb. 7",
"Bankverb 7 gültig von",
"Bankverb 7 gültig bis",
"Bankleitzahl 8",
"Bankbezeichnung 8",
"Bankkonto-Nummer 8",
"Länderkennzeichen 8",
"IBAN 8",
"Leerfeld 9",
"SWIFT-Code 8",
"Abw. Kontoinhaber 8",
"Kennz. Haupt-Bankverb. 8",
"Bankverb 8 gültig von",
"Bankverb 8 gültig bis",
"Bankleitzahl 9",
"Bankbezeichnung 9",
"Bankkonto-Nummer 9",
"Länderkennzeichen 9",
"IBAN 9",
"Leerfeld 10",
"SWIFT-Code 9",
"Abw. Kontoinhaber 9",
"Kennz. Haupt-Bankverb. 9",
"Bankverb 9 gültig von",
"Bankverb 9 gültig bis",
"Bankleitzahl 10",
"Bankbezeichnung 10",
"Bankkonto-Nummer 10",
"Länderkennzeichen 10",
"IBAN 10",
"Leerfeld 11",
"SWIFT-Code 10",
"Abw. Kontoinhaber 10",
"Kennz. Haupt-Bankverb. 10",
"Bankverb 10 gültig von",
"Bankverb 10 gültig bis",
"Nummer Fremdsystem",
"Insolvent",
"SEPA-Mandatsreferenz 1",
"SEPA-Mandatsreferenz 2",
"SEPA-Mandatsreferenz 3",
"SEPA-Mandatsreferenz 4",
"SEPA-Mandatsreferenz 5",
"SEPA-Mandatsreferenz 6",
"SEPA-Mandatsreferenz 7",
"SEPA-Mandatsreferenz 8",
"SEPA-Mandatsreferenz 9",
"SEPA-Mandatsreferenz 10",
"Verknüpftes OPOS-Konto",
"Mahnsperre bis",
"Lastschriftsperre bis",
"Zahlungssperre bis",
"Gebührenberechnung",
"Mahngebühr 1",
"Mahngebühr 2",
"Mahngebühr 3",
"Pauschalberechnung",
"Verzugspauschale 1",
"Verzugspauschale 2",
"Verzugspauschale 3",
"Alternativer Suchname",
"Status",
"Anschrift manuell geändert (Korrespondenzadresse)",
"Anschrift individuell (Korrespondenzadresse)",
"Anschrift manuell geändert (Rechnungsadresse)",
"Anschrift individuell (Rechnungsadresse)",
"Fristberechnung bei Debitor",
"Mahnfrist 1",
"Mahnfrist 2",
"Mahnfrist 3",
"Letzte Frist"
]
ACCOUNT_NAME_COLUMNS = [
# Account number
"Konto",
# Account name
"Kontenbeschriftung",
# Language of the account name
# "de-DE" or "en-GB"
"Sprach-ID"
]
QUERY_REPORT_COLUMNS = [
{
"label": "Umsatz (ohne Soll/Haben-Kz)",
"fieldname": "Umsatz (ohne Soll/Haben-Kz)",
"fieldtype": "Currency",
},
{
"label": "Soll/Haben-Kennzeichen",
"fieldname": "Soll/Haben-Kennzeichen",
"fieldtype": "Data",
},
{
"label": "Kontonummer",
"fieldname": "Kontonummer",
"fieldtype": "Data",
},
{
"label": "Gegenkonto (ohne BU-Schlüssel)",
"fieldname": "Gegenkonto (ohne BU-Schlüssel)",
"fieldtype": "Data",
},
{
"label": "Belegdatum",
"fieldname": "Belegdatum",
"fieldtype": "Date",
},
{
"label": "Buchungstext",
"fieldname": "Buchungstext",
"fieldtype": "Text",
},
{
"label": "Beleginfo - Art 1",
"fieldname": "Beleginfo - Art 1",
"fieldtype": "Data",
},
{
"label": "Beleginfo - Inhalt 1",
"fieldname": "Beleginfo - Inhalt 1",
"fieldtype": "Data",
},
{
"label": "Beleginfo - Art 2",
"fieldname": "Beleginfo - Art 2",
"fieldtype": "Data",
},
{
"label": "Beleginfo - Inhalt 2",
"fieldname": "Beleginfo - Inhalt 2",
"fieldtype": "Data",
}
]
class DataCategory():
"""Field of the CSV Header."""
DEBTORS_CREDITORS = "16"
ACCOUNT_NAMES = "20"
TRANSACTIONS = "21"
POSTING_TEXT_CONSTANTS = "67"
class FormatName():
"""Field of the CSV Header, corresponds to DataCategory."""
DEBTORS_CREDITORS = "Debitoren/Kreditoren"
ACCOUNT_NAMES = "Kontenbeschriftungen"
TRANSACTIONS = "Buchungsstapel"
POSTING_TEXT_CONSTANTS = "Buchungstextkonstanten"
class Transactions():
DATA_CATEGORY = DataCategory.TRANSACTIONS
FORMAT_NAME = FormatName.TRANSACTIONS
COLUMNS = TRANSACTION_COLUMNS
class DebtorsCreditors():
DATA_CATEGORY = DataCategory.DEBTORS_CREDITORS
FORMAT_NAME = FormatName.DEBTORS_CREDITORS
COLUMNS = DEBTOR_CREDITOR_COLUMNS
class AccountNames():
DATA_CATEGORY = DataCategory.ACCOUNT_NAMES
FORMAT_NAME = FormatName.ACCOUNT_NAMES
COLUMNS = ACCOUNT_NAME_COLUMNS

View File

@ -0,0 +1,244 @@
# coding=utf-8
from __future__ import unicode_literals
import os
import json
import zipfile
from six import BytesIO
from unittest import TestCase
import frappe
from frappe.utils import getdate, today, now_datetime, cstr
from frappe.test_runner import make_test_objects
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import create_charts
from erpnext.regional.report.datev.datev import validate
from erpnext.regional.report.datev.datev import get_transactions
from erpnext.regional.report.datev.datev import get_customers
from erpnext.regional.report.datev.datev import get_suppliers
from erpnext.regional.report.datev.datev import get_account_names
from erpnext.regional.report.datev.datev import get_datev_csv
from erpnext.regional.report.datev.datev import get_header
from erpnext.regional.report.datev.datev import download_datev_csv
from erpnext.regional.report.datev.datev_constants import DataCategory
from erpnext.regional.report.datev.datev_constants import Transactions
from erpnext.regional.report.datev.datev_constants import DebtorsCreditors
from erpnext.regional.report.datev.datev_constants import AccountNames
from erpnext.regional.report.datev.datev_constants import QUERY_REPORT_COLUMNS
def make_company(company_name, abbr):
if not frappe.db.exists("Company", company_name):
company = frappe.get_doc({
"doctype": "Company",
"company_name": company_name,
"abbr": abbr,
"default_currency": "EUR",
"country": "Germany",
"create_chart_of_accounts_based_on": "Standard Template",
"chart_of_accounts": "SKR04 mit Kontonummern"
})
company.insert()
else:
company = frappe.get_doc("Company", company_name)
# indempotent
company.create_default_warehouses()
if not frappe.db.get_value("Cost Center", {"is_group": 0, "company": company.name}):
company.create_default_cost_center()
company.save()
return company
def setup_fiscal_year():
fiscal_year = None
year = cstr(now_datetime().year)
if not frappe.db.get_value("Fiscal Year", {"year": year}, "name"):
try:
fiscal_year = frappe.get_doc({
"doctype": "Fiscal Year",
"year": year,
"year_start_date": "{0}-01-01".format(year),
"year_end_date": "{0}-12-31".format(year)
})
fiscal_year.insert()
except frappe.NameError:
pass
if fiscal_year:
fiscal_year.set_as_default()
def make_customer_with_account(customer_name, company):
acc_name = frappe.db.get_value("Account", {
"account_name": customer_name,
"company": company.name
}, "name")
if not acc_name:
acc = frappe.get_doc({
"doctype": "Account",
"parent_account": "1 - Forderungen aus Lieferungen und Leistungen - _TG",
"account_name": customer_name,
"company": company.name,
"account_type": "Receivable",
"account_number": "10001"
})
acc.insert()
acc_name = acc.name
if not frappe.db.exists("Customer", customer_name):
customer = frappe.get_doc({
"doctype": "Customer",
"customer_name": customer_name,
"customer_type": "Company",
"accounts": [{
"company": company.name,
"account": acc_name
}]
})
customer.insert()
else:
customer = frappe.get_doc("Customer", customer_name)
return customer
def make_item(item_code, company):
warehouse_name = frappe.db.get_value("Warehouse", {
"warehouse_name": "Stores",
"company": company.name
}, "name")
if not frappe.db.exists("Item", item_code):
item = frappe.get_doc({
"doctype": "Item",
"item_code": item_code,
"item_name": item_code,
"description": item_code,
"item_group": "All Item Groups",
"is_stock_item": 0,
"is_purchase_item": 0,
"is_customer_provided_item": 0,
"item_defaults": [{
"default_warehouse": warehouse_name,
"company": company.name
}]
})
item.insert()
else:
item = frappe.get_doc("Item", item_code)
return item
def make_datev_settings(company):
if not frappe.db.exists("DATEV Settings", company.name):
frappe.get_doc({
"doctype": "DATEV Settings",
"client": company.name,
"client_number": "12345",
"consultant_number": "67890"
}).insert()
class TestDatev(TestCase):
def setUp(self):
self.company = make_company("_Test GmbH", "_TG")
self.customer = make_customer_with_account("_Test Kunde GmbH", self.company)
self.filters = {
"company": self.company.name,
"from_date": today(),
"to_date": today()
}
make_datev_settings(self.company)
item = make_item("_Test Item", self.company)
setup_fiscal_year()
warehouse = frappe.db.get_value("Item Default", {
"parent": item.name,
"company": self.company.name
}, "default_warehouse")
income_account = frappe.db.get_value("Account", {
"account_number": "4200",
"company": self.company.name
}, "name")
tax_account = frappe.db.get_value("Account", {
"account_number": "3806",
"company": self.company.name
}, "name")
si = create_sales_invoice(
company=self.company.name,
customer=self.customer.name,
currency=self.company.default_currency,
debit_to=self.customer.accounts[0].account,
income_account="4200 - Erlöse - _TG",
expense_account="6990 - Herstellungskosten - _TG",
cost_center=self.company.cost_center,
warehouse=warehouse,
item=item.name,
do_not_save=1
)
si.append("taxes", {
"charge_type": "On Net Total",
"account_head": tax_account,
"description": "Umsatzsteuer 19 %",
"rate": 19
})
si.save()
si.submit()
def test_columns(self):
def is_subset(get_data, allowed_keys):
"""
Validate that the dict contains only allowed keys.
Params:
get_data -- Function that returns a list of dicts.
allowed_keys -- List of allowed keys
"""
data = get_data(self.filters)
if data == []:
# No data and, therefore, no columns is okay
return True
actual_set = set(data[0].keys())
# allowed set must be interpreted as unicode to match the actual set
allowed_set = set({frappe.as_unicode(key) for key in allowed_keys})
return actual_set.issubset(allowed_set)
self.assertTrue(is_subset(get_transactions, Transactions.COLUMNS))
self.assertTrue(is_subset(get_customers, DebtorsCreditors.COLUMNS))
self.assertTrue(is_subset(get_suppliers, DebtorsCreditors.COLUMNS))
self.assertTrue(is_subset(get_account_names, AccountNames.COLUMNS))
def test_header(self):
self.assertTrue(Transactions.DATA_CATEGORY in get_header(self.filters, Transactions))
self.assertTrue(AccountNames.DATA_CATEGORY in get_header(self.filters, AccountNames))
self.assertTrue(DebtorsCreditors.DATA_CATEGORY in get_header(self.filters, DebtorsCreditors))
def test_csv(self):
test_data = [{
"Umsatz (ohne Soll/Haben-Kz)": 100,
"Soll/Haben-Kennzeichen": "H",
"Kontonummer": "4200",
"Gegenkonto (ohne BU-Schlüssel)": "10000",
"Belegdatum": today(),
"Buchungstext": "No remark",
"Beleginfo - Art 1": "Sales Invoice",
"Beleginfo - Inhalt 1": "SINV-0001"
}]
get_datev_csv(data=test_data, filters=self.filters, csv_class=Transactions)
def test_download(self):
"""Assert that the returned file is a ZIP file."""
download_datev_csv(self.filters)
# zipfile.is_zipfile() expects a file-like object
zip_buffer = BytesIO()
zip_buffer.write(frappe.response['filecontent'])
self.assertTrue(zipfile.is_zipfile(zip_buffer))

View File

@ -52,7 +52,7 @@ frappe.query_reports["GSTR-1"] = {
], ],
onload: function (report) { onload: function (report) {
report.page.add_inner_button(__("Download as Json"), function () { report.page.add_inner_button(__("Download as JSON"), function () {
var filters = report.get_values(); var filters = report.get_values();
const args = { const args = {

View File

@ -204,6 +204,40 @@ class Customer(TransactionBase):
else: else:
frappe.msgprint(_("Multiple Loyalty Program found for the Customer. Please select manually.")) frappe.msgprint(_("Multiple Loyalty Program found for the Customer. Please select manually."))
def create_onboarding_docs(self, args):
defaults = frappe.defaults.get_defaults()
for i in range(1, args.get('max_count')):
customer = args.get('customer_name_' + str(i))
if customer:
try:
doc = frappe.get_doc({
'doctype': self.doctype,
'customer_name': customer,
'customer_type': 'Company',
'customer_group': _('Commercial'),
'territory': defaults.get('country'),
'company': defaults.get('company')
}).insert()
if args.get('customer_email_' + str(i)):
create_contact(customer, self.doctype,
doc.name, args.get("customer_email_" + str(i)))
except frappe.NameError:
pass
def create_contact(contact, party_type, party, email):
"""Create contact based on given contact name"""
contact = contact.split(' ')
contact = frappe.get_doc({
'doctype': 'Contact',
'first_name': contact[0],
'last_name': len(contact) > 1 and contact[1] or ""
})
contact.append('email_ids', dict(email_id=email, is_primary=1))
contact.append('links', dict(link_doctype=party_type, link_name=party))
contact.insert()
@frappe.whitelist() @frappe.whitelist()
def get_loyalty_programs(doc): def get_loyalty_programs(doc):
''' returns applicable loyalty programs for a customer ''' ''' returns applicable loyalty programs for a customer '''

View File

@ -834,6 +834,10 @@ def make_purchase_order(source_name, for_supplier=None, selected_items=[], targe
for item in sales_order.items: for item in sales_order.items:
if item.supplier and item.supplier not in suppliers: if item.supplier and item.supplier not in suppliers:
suppliers.append(item.supplier) suppliers.append(item.supplier)
if not suppliers:
frappe.throw(_("Please set a Supplier against the Items to be considered in the Purchase Order."))
for supplier in suppliers: for supplier in suppliers:
po =frappe.get_list("Purchase Order", filters={"sales_order":source_name, "supplier":supplier, "docstatus": ("<", "2")}) po =frappe.get_list("Purchase Order", filters={"sales_order":source_name, "supplier":supplier, "docstatus": ("<", "2")})
if len(po) == 0: if len(po) == 0:

View File

@ -0,0 +1,49 @@
{
"add_more_button": 1,
"app": "ERPNext",
"creation": "2019-11-15 14:44:10.065014",
"docstatus": 0,
"doctype": "Setup Wizard Slide",
"domains": [],
"help_links": [
{
"label": "Customers",
"video_id": "zsrrVDk6VBs"
}
],
"idx": 0,
"image_src": "/assets/erpnext/images/illustrations/customer.png",
"max_count": 3,
"modified": "2019-11-26 18:26:15.888794",
"modified_by": "Administrator",
"name": "Add A Few Customers",
"owner": "Administrator",
"ref_doctype": "Customer",
"slide_desc": "",
"slide_fields": [
{
"align": "",
"fieldname": "customer_name",
"fieldtype": "Data",
"label": "Customer Name",
"placeholder": "",
"reqd": 1
},
{
"align": "",
"fieldtype": "Column Break",
"reqd": 0
},
{
"align": "",
"fieldname": "customer_email",
"fieldtype": "Data",
"label": "Email ID",
"reqd": 1
}
],
"slide_order": 40,
"slide_title": "Add A Few Customers",
"slide_type": "Create",
"submit_method": ""
}

View File

@ -1,8 +0,0 @@
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Setup Progress', {
refresh: function() {
}
});

View File

@ -1,123 +0,0 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2017-08-27 21:01:42.032109",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "actions_sb",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Actions",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "actions",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Actions",
"length": 0,
"no_copy": 0,
"options": "Setup Progress Action",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 1,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2017-09-21 11:52:56.106659",
"modified_by": "Administrator",
"module": "Setup",
"name": "Setup Progress",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 0,
"role": "All",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
],
"quick_entry": 1,
"read_only": 1,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
}

View File

@ -1,63 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe, json
from frappe.model.document import Document
class SetupProgress(Document):
pass
def get_setup_progress():
if not getattr(frappe.local, "setup_progress", None):
frappe.local.setup_progress = frappe.get_doc("Setup Progress", "Setup Progress")
return frappe.local.setup_progress
def get_action_completed_state(action_name):
for d in get_setup_progress().actions:
if d.action_name == action_name:
return d.is_completed
def update_action_completed_state(action_name):
action_table_doc = [d for d in get_setup_progress().actions
if d.action_name == action_name][0]
update_action(action_table_doc)
def update_action(doc):
doctype = doc.action_doctype
docname = doc.action_document
field = doc.action_field
if not doc.is_completed:
if doc.min_doc_count:
if frappe.db.count(doctype) >= doc.min_doc_count:
doc.is_completed = 1
doc.save()
if docname and field:
d = frappe.get_doc(doctype, docname)
if d.get(field):
doc.is_completed = 1
doc.save()
def update_domain_actions(domain):
for d in get_setup_progress().actions:
domains = json.loads(d.domains)
if domains == [] or domain in domains:
update_action(d)
def get_domain_actions_state(domain):
state = {}
for d in get_setup_progress().actions:
domains = json.loads(d.domains)
if domains == [] or domain in domains:
state[d.action_name] = d.is_completed
return state
@frappe.whitelist()
def set_action_completed_state(action_name):
action_table_doc = [d for d in get_setup_progress().actions
if d.action_name == action_name][0]
action_table_doc.is_completed = 1
action_table_doc.save()

View File

@ -1,23 +0,0 @@
/* eslint-disable */
// rename this file from _test_[name] to test_[name] to activate
// and remove above this line
QUnit.test("test: Setup Progress", function (assert) {
let done = assert.async();
// number of asserts
assert.expect(1);
frappe.run_serially([
// insert a new Setup Progress
() => frappe.tests.make('Setup Progress', [
// values to be set
{key: 'value'}
]),
() => {
assert.equal(cur_frm.doc.key, 'value');
},
() => done()
]);
});

View File

@ -1,9 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
import unittest
class TestSetupProgress(unittest.TestCase):
pass

View File

@ -1,253 +0,0 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2017-08-27 21:00:40.715360",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "action_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Action Name",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "action_doctype",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Action Doctype",
"length": 0,
"no_copy": 0,
"options": "DocType",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "action_document",
"fieldtype": "Dynamic Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Action Document",
"length": 0,
"no_copy": 0,
"options": "action_doctype",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "action_field",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Action Field",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "min_doc_count",
"fieldtype": "Int",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Min Doc Count",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "domains",
"fieldtype": "Code",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Domains",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "is_completed",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Is Completed",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 1,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-09-01 14:34:59.685730",
"modified_by": "Administrator",
"module": "Setup",
"name": "Setup Progress Action",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 1,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
}

View File

@ -1,9 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
from frappe.model.document import Document
class SetupProgressAction(Document):
pass

View File

@ -1,71 +0,0 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe, time
from frappe.utils.selenium_testdriver import TestDriver
def run_setup_wizard_test():
driver = TestDriver()
frappe.db.set_default('in_selenium', '1')
frappe.db.commit()
driver.login('#page-setup-wizard')
print('Running Setup Wizard Test...')
# Language slide
driver.wait_for_ajax(True)
time.sleep(1)
driver.set_select("language", "English (United States)")
driver.wait_for_ajax(True)
time.sleep(1)
driver.click(".next-btn")
# Region slide
driver.wait_for_ajax(True)
driver.set_select("country", "India")
driver.wait_for_ajax(True)
time.sleep(1)
driver.click(".next-btn")
# Profile slide
driver.set_field("full_name", "Great Tester")
driver.set_field("email", "great@example.com")
driver.set_field("password", "test")
driver.wait_for_ajax(True)
time.sleep(1)
driver.click(".next-btn")
time.sleep(1)
# domain slide
driver.set_multicheck("domains", ["Manufacturing"])
time.sleep(1)
driver.click(".next-btn")
# Org slide
driver.set_field("company_name", "For Testing")
time.sleep(1)
driver.print_console()
driver.click(".next-btn")
driver.set_field("company_tagline", "Just for GST")
driver.set_field("bank_account", "HDFC")
time.sleep(3)
driver.click(".complete-btn")
# Wait for desktop
driver.wait_for('#page-desktop', timeout=600)
driver.print_console()
time.sleep(3)
frappe.db.set_default('in_selenium', None)
frappe.db.set_value("Company", "For Testing", "write_off_account", "Write Off - FT")
frappe.db.set_value("Company", "For Testing", "exchange_gain_loss_account", "Exchange Gain/Loss - FT")
frappe.db.commit()
driver.close()
return True

View File

@ -0,0 +1,22 @@
{
"add_more_button": 0,
"app": "ERPNext",
"creation": "2019-11-26 17:01:26.671859",
"docstatus": 0,
"doctype": "Setup Wizard Slide",
"domains": [],
"help_links": [],
"idx": 0,
"image_src": "/assets/erpnext/images/illustrations/onboard.png",
"max_count": 0,
"modified": "2019-11-26 17:17:29.813299",
"modified_by": "Administrator",
"name": "Welcome to ERPNext!",
"owner": "Administrator",
"slide_desc": "Setting up an ERP can be overwhelming. But don't worry, we have got your back!<br>\nLet's setup your company.\nThis wizard will help you onboard to ERPNext in a short time!",
"slide_fields": [],
"slide_module": "Setup",
"slide_order": 10,
"slide_title": "Welcome to ERPNext!",
"slide_type": "Information"
}

View File

@ -66,6 +66,7 @@ def place_order():
from erpnext.selling.doctype.quotation.quotation import _make_sales_order from erpnext.selling.doctype.quotation.quotation import _make_sales_order
sales_order = frappe.get_doc(_make_sales_order(quotation.name, ignore_permissions=True)) sales_order = frappe.get_doc(_make_sales_order(quotation.name, ignore_permissions=True))
sales_order.payment_schedule = []
if not cint(cart_settings.allow_items_not_in_stock): if not cint(cart_settings.allow_items_not_in_stock):
for item in sales_order.get("items"): for item in sales_order.get("items"):

View File

@ -136,6 +136,20 @@ frappe.ui.form.on("Item", {
frm.toggle_reqd('customer', frm.doc.is_customer_provided_item ? 1:0); frm.toggle_reqd('customer', frm.doc.is_customer_provided_item ? 1:0);
}, },
gst_hsn_code: function(frm){
if(!frm.doc.taxes){
frappe.db.get_doc("GST HSN Code", frm.doc.gst_hsn_code).then(hsn_doc=>{
frm.doc.taxes = [];
$.each(hsn_doc.taxes || [], function(i, tax) {
let a = frappe.model.add_child(cur_frm.doc, 'Item Tax', 'taxes');
a.item_tax_template = tax.item_tax_template;
a.tax_category = tax.tax_category;
frm.refresh_field('taxes');
});
});
}
},
is_fixed_asset: function(frm) { is_fixed_asset: function(frm) {
// set serial no to false & toggles its visibility // set serial no to false & toggles its visibility
frm.set_value('has_serial_no', 0); frm.set_value('has_serial_no', 0);

View File

@ -884,6 +884,54 @@ class Item(WebsiteGenerator):
if not enabled: if not enabled:
frappe.msgprint(msg=_("You have to enable auto re-order in Stock Settings to maintain re-order levels."), title=_("Enable Auto Re-Order"), indicator="orange") frappe.msgprint(msg=_("You have to enable auto re-order in Stock Settings to maintain re-order levels."), title=_("Enable Auto Re-Order"), indicator="orange")
def create_onboarding_docs(self, args):
defaults = frappe.defaults.get_defaults()
for i in range(1, args.get('max_count')):
item = args.get('item_' + str(i))
if item:
default_warehouse = ''
default_warehouse = frappe.db.get_value('Warehouse', filters={
'warehouse_name': _('Finished Goods'),
'company': defaults.get('company_name')
})
try:
frappe.get_doc({
'doctype': self.doctype,
'item_code': item,
'item_name': item,
'description': item,
'show_in_website': 1,
'is_sales_item': 1,
'is_purchase_item': 1,
'is_stock_item': 1,
'item_group': _('Products'),
'stock_uom': _(args.get('item_uom_' + str(i))),
'item_defaults': [{
'default_warehouse': default_warehouse,
'company': defaults.get('company_name')
}]
}).insert()
except frappe.NameError:
pass
else:
if args.get('item_price_' + str(i)):
item_price = flt(args.get('tem_price_' + str(i)))
price_list_name = frappe.db.get_value('Price List', {'selling': 1})
make_item_price(item, price_list_name, item_price)
price_list_name = frappe.db.get_value('Price List', {'buying': 1})
make_item_price(item, price_list_name, item_price)
def make_item_price(item, price_list_name, item_price):
frappe.get_doc({
'doctype': 'Item Price',
'price_list': price_list_name,
'item_code': item,
'price_list_rate': item_price
}).insert()
def get_timeline_data(doctype, name): def get_timeline_data(doctype, name):
'''returns timeline data based on stock ledger entry''' '''returns timeline data based on stock ledger entry'''
out = {} out = {}

View File

@ -34,6 +34,12 @@ frappe.ui.form.on("Purchase Receipt", {
filters: {'company': frm.doc.company } filters: {'company': frm.doc.company }
} }
}); });
frm.set_query("taxes_and_charges", function() {
return {
filters: {'company': frm.doc.company }
}
});
}, },
onload: function(frm) { onload: function(frm) {
@ -296,4 +302,4 @@ var validate_sample_quantity = function(frm, cdt, cdn) {
} }
}); });
} }
}; };

View File

@ -16,7 +16,7 @@ frappe.ui.form.on('Quick Stock Balance', {
frm.add_custom_button(__('Stock Balance Report'), () => { frm.add_custom_button(__('Stock Balance Report'), () => {
frappe.set_route('query-report', 'Stock Balance', frappe.set_route('query-report', 'Stock Balance',
{ 'item_code': frm.doc.item, 'warehouse': frm.doc.warehouse }); { 'item_code': frm.doc.item, 'warehouse': frm.doc.warehouse });
}).addClass("btn-primary"); });
} }
}, },

View File

@ -1,874 +1,299 @@
{ {
"allow_copy": 1, "allow_copy": 1,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "MAT-SLE-.YYYY.-.#####", "autoname": "MAT-SLE-.YYYY.-.#####",
"beta": 0,
"creation": "2013-01-29 19:25:42", "creation": "2013-01-29 19:25:42",
"custom": 0,
"docstatus": 0,
"doctype": "DocType", "doctype": "DocType",
"document_type": "Other", "document_type": "Other",
"editable_grid": 0,
"engine": "InnoDB", "engine": "InnoDB",
"field_order": [
"item_code",
"serial_no",
"batch_no",
"warehouse",
"posting_date",
"posting_time",
"voucher_type",
"voucher_no",
"voucher_detail_no",
"actual_qty",
"incoming_rate",
"outgoing_rate",
"stock_uom",
"qty_after_transaction",
"valuation_rate",
"stock_value",
"stock_value_difference",
"stock_queue",
"project",
"company",
"fiscal_year",
"is_cancelled",
"to_rename"
],
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "item_code", "fieldname": "item_code",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1, "in_filter": 1,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 1, "in_standard_filter": 1,
"label": "Item Code", "label": "Item Code",
"length": 0,
"no_copy": 0,
"oldfieldname": "item_code", "oldfieldname": "item_code",
"oldfieldtype": "Link", "oldfieldtype": "Link",
"options": "Item", "options": "Item",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "100px", "print_width": "100px",
"read_only": 1, "read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 1, "search_index": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "100px" "width": "100px"
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "serial_no", "fieldname": "serial_no",
"fieldtype": "Text", "fieldtype": "Long Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0,
"label": "Serial No", "label": "Serial No",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "100px", "print_width": "100px",
"read_only": 1, "read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "100px" "width": "100px"
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "batch_no", "fieldname": "batch_no",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0,
"label": "Batch No", "label": "Batch No",
"length": 0,
"no_copy": 0,
"oldfieldname": "batch_no", "oldfieldname": "batch_no",
"oldfieldtype": "Data", "oldfieldtype": "Data",
"permlevel": 0, "read_only": 1
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "warehouse", "fieldname": "warehouse",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1, "in_filter": 1,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 1, "in_standard_filter": 1,
"label": "Warehouse", "label": "Warehouse",
"length": 0,
"no_copy": 0,
"oldfieldname": "warehouse", "oldfieldname": "warehouse",
"oldfieldtype": "Link", "oldfieldtype": "Link",
"options": "Warehouse", "options": "Warehouse",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "100px", "print_width": "100px",
"read_only": 1, "read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 1, "search_index": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "100px" "width": "100px"
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "posting_date", "fieldname": "posting_date",
"fieldtype": "Date", "fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1, "in_filter": 1,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0,
"label": "Posting Date", "label": "Posting Date",
"length": 0,
"no_copy": 0,
"oldfieldname": "posting_date", "oldfieldname": "posting_date",
"oldfieldtype": "Date", "oldfieldtype": "Date",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "100px", "print_width": "100px",
"read_only": 1, "read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 1, "search_index": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "100px" "width": "100px"
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "posting_time", "fieldname": "posting_time",
"fieldtype": "Time", "fieldtype": "Time",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Posting Time", "label": "Posting Time",
"length": 0,
"no_copy": 0,
"oldfieldname": "posting_time", "oldfieldname": "posting_time",
"oldfieldtype": "Time", "oldfieldtype": "Time",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "100px", "print_width": "100px",
"read_only": 1, "read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "100px" "width": "100px"
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "voucher_type", "fieldname": "voucher_type",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1, "in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Voucher Type", "label": "Voucher Type",
"length": 0,
"no_copy": 0,
"oldfieldname": "voucher_type", "oldfieldname": "voucher_type",
"oldfieldtype": "Data", "oldfieldtype": "Data",
"options": "DocType", "options": "DocType",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "150px", "print_width": "150px",
"read_only": 1, "read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "150px" "width": "150px"
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "voucher_no", "fieldname": "voucher_no",
"fieldtype": "Dynamic Link", "fieldtype": "Dynamic Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1, "in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 1, "in_standard_filter": 1,
"label": "Voucher No", "label": "Voucher No",
"length": 0,
"no_copy": 0,
"oldfieldname": "voucher_no", "oldfieldname": "voucher_no",
"oldfieldtype": "Data", "oldfieldtype": "Data",
"options": "voucher_type", "options": "voucher_type",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "150px", "print_width": "150px",
"read_only": 1, "read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "150px" "width": "150px"
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "voucher_detail_no", "fieldname": "voucher_detail_no",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Voucher Detail No", "label": "Voucher Detail No",
"length": 0,
"no_copy": 0,
"oldfieldname": "voucher_detail_no", "oldfieldname": "voucher_detail_no",
"oldfieldtype": "Data", "oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "150px", "print_width": "150px",
"read_only": 1, "read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "150px" "width": "150px"
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "actual_qty", "fieldname": "actual_qty",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1, "in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Actual Quantity", "label": "Actual Quantity",
"length": 0,
"no_copy": 0,
"oldfieldname": "actual_qty", "oldfieldname": "actual_qty",
"oldfieldtype": "Currency", "oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "150px", "print_width": "150px",
"read_only": 1, "read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "150px" "width": "150px"
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "incoming_rate", "fieldname": "incoming_rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Incoming Rate", "label": "Incoming Rate",
"length": 0,
"no_copy": 0,
"oldfieldname": "incoming_rate", "oldfieldname": "incoming_rate",
"oldfieldtype": "Currency", "oldfieldtype": "Currency",
"options": "Company:company:default_currency", "options": "Company:company:default_currency",
"permlevel": 0, "read_only": 1
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "outgoing_rate", "fieldname": "outgoing_rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Outgoing Rate", "label": "Outgoing Rate",
"length": 0,
"no_copy": 0,
"options": "Company:company:default_currency", "options": "Company:company:default_currency",
"permlevel": 0, "read_only": 1
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "stock_uom", "fieldname": "stock_uom",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Stock UOM", "label": "Stock UOM",
"length": 0,
"no_copy": 0,
"oldfieldname": "stock_uom", "oldfieldname": "stock_uom",
"oldfieldtype": "Data", "oldfieldtype": "Data",
"options": "UOM", "options": "UOM",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "150px", "print_width": "150px",
"read_only": 1, "read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "150px" "width": "150px"
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "qty_after_transaction", "fieldname": "qty_after_transaction",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1, "in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Actual Qty After Transaction", "label": "Actual Qty After Transaction",
"length": 0,
"no_copy": 0,
"oldfieldname": "bin_aqat", "oldfieldname": "bin_aqat",
"oldfieldtype": "Currency", "oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "150px", "print_width": "150px",
"read_only": 1, "read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "150px" "width": "150px"
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "valuation_rate", "fieldname": "valuation_rate",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Valuation Rate", "label": "Valuation Rate",
"length": 0,
"no_copy": 0,
"oldfieldname": "valuation_rate", "oldfieldname": "valuation_rate",
"oldfieldtype": "Currency", "oldfieldtype": "Currency",
"options": "Company:company:default_currency", "options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "150px", "print_width": "150px",
"read_only": 1, "read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "150px" "width": "150px"
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "stock_value", "fieldname": "stock_value",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Stock Value", "label": "Stock Value",
"length": 0,
"no_copy": 0,
"oldfieldname": "stock_value", "oldfieldname": "stock_value",
"oldfieldtype": "Currency", "oldfieldtype": "Currency",
"options": "Company:company:default_currency", "options": "Company:company:default_currency",
"permlevel": 0, "read_only": 1
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "stock_value_difference", "fieldname": "stock_value_difference",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Stock Value Difference", "label": "Stock Value Difference",
"length": 0,
"no_copy": 0,
"options": "Company:company:default_currency", "options": "Company:company:default_currency",
"permlevel": 0, "read_only": 1
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "stock_queue", "fieldname": "stock_queue",
"fieldtype": "Text", "fieldtype": "Text",
"hidden": 1, "hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Stock Queue (FIFO)", "label": "Stock Queue (FIFO)",
"length": 0,
"no_copy": 0,
"oldfieldname": "fcfs_stack", "oldfieldname": "fcfs_stack",
"oldfieldtype": "Text", "oldfieldtype": "Text",
"permlevel": 0,
"print_hide": 1, "print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1, "read_only": 1,
"remember_last_selected_value": 0, "report_hide": 1
"report_hide": 1,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "project", "fieldname": "project",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Project", "label": "Project",
"length": 0, "options": "Project"
"no_copy": 0,
"options": "Project",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "company", "fieldname": "company",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1, "in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Company", "label": "Company",
"length": 0,
"no_copy": 0,
"oldfieldname": "company", "oldfieldname": "company",
"oldfieldtype": "Data", "oldfieldtype": "Data",
"options": "Company", "options": "Company",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "150px", "print_width": "150px",
"read_only": 1, "read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "150px" "width": "150px"
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "fiscal_year", "fieldname": "fiscal_year",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1, "in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Fiscal Year", "label": "Fiscal Year",
"length": 0,
"no_copy": 0,
"oldfieldname": "fiscal_year", "oldfieldname": "fiscal_year",
"oldfieldtype": "Data", "oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "150px", "print_width": "150px",
"read_only": 1, "read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "150px" "width": "150px"
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "is_cancelled", "fieldname": "is_cancelled",
"fieldtype": "Select", "fieldtype": "Select",
"hidden": 1, "hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Is Cancelled", "label": "Is Cancelled",
"length": 0,
"no_copy": 0,
"options": "\nNo\nYes", "options": "\nNo\nYes",
"permlevel": 0, "report_hide": 1
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 1,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "1", "default": "1",
"fieldname": "to_rename", "fieldname": "to_rename",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 1, "hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "To Rename", "label": "To Rename",
"length": 0, "search_index": 1
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0
} }
], ],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 1, "hide_toolbar": 1,
"icon": "fa fa-list", "icon": "fa fa-list",
"idx": 1, "idx": 1,
"image_view": 0,
"in_create": 1, "in_create": 1,
"is_submittable": 0, "modified": "2019-11-27 12:17:31.522675",
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2019-01-07 07:04:37.523024",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Stock", "module": "Stock",
"name": "Stock Ledger Entry", "name": "Stock Ledger Entry",
"owner": "Administrator", "owner": "Administrator",
"permissions": [ "permissions": [
{ {
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 0,
"export": 1, "export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1, "print": 1,
"read": 1, "read": 1,
"report": 1, "report": 1,
"role": "Stock User", "role": "Stock User"
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
}, },
{ {
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 0,
"export": 1, "export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 0,
"read": 1, "read": 1,
"report": 1, "report": 1,
"role": "Accounts Manager", "role": "Accounts Manager"
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
} }
], ],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC"
"track_changes": 0,
"track_seen": 0,
"track_views": 0
} }

View File

@ -254,6 +254,12 @@ def get_basic_details(args, item, overwrite_warehouse=True):
args['material_request_type'] = frappe.db.get_value('Material Request', args['material_request_type'] = frappe.db.get_value('Material Request',
args.get('name'), 'material_request_type', cache=True) args.get('name'), 'material_request_type', cache=True)
expense_account = None
if args.get('doctype') == 'Purchase Invoice' and item.is_fixed_asset:
from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
expense_account = get_asset_category_account(fieldname = "fixed_asset_account", item = args.item_code, company= args.company)
#Set the UOM to the Default Sales UOM or Default Purchase UOM if configured in the Item Master #Set the UOM to the Default Sales UOM or Default Purchase UOM if configured in the Item Master
if not args.uom: if not args.uom:
if args.get('doctype') in sales_doctypes: if args.get('doctype') in sales_doctypes:
@ -271,7 +277,7 @@ def get_basic_details(args, item, overwrite_warehouse=True):
"image": cstr(item.image).strip(), "image": cstr(item.image).strip(),
"warehouse": warehouse, "warehouse": warehouse,
"income_account": get_default_income_account(args, item_defaults, item_group_defaults, brand_defaults), "income_account": get_default_income_account(args, item_defaults, item_group_defaults, brand_defaults),
"expense_account": get_default_expense_account(args, item_defaults, item_group_defaults, brand_defaults), "expense_account": expense_account or get_default_expense_account(args, item_defaults, item_group_defaults, brand_defaults) ,
"cost_center": get_default_cost_center(args, item_defaults, item_group_defaults, brand_defaults), "cost_center": get_default_cost_center(args, item_defaults, item_group_defaults, brand_defaults),
'has_serial_no': item.has_serial_no, 'has_serial_no': item.has_serial_no,
'has_batch_no': item.has_batch_no, 'has_batch_no': item.has_batch_no,

View File

@ -15,7 +15,7 @@
"prepared_report": 0, "prepared_report": 0,
"query": "SELECT\n\t`poi_pri`.`purchase_order` as \"Purchase Order:Link/Purchase Order:120\",\n\t`poi_pri`.`status` as \"Status:Data:120\",\n\t`poi_pri`.`transaction_date` as \"Date:Date:100\",\n\t`poi_pri`.`schedule_date` as \"Reqd by Date:Date:110\",\n\t`poi_pri`.`supplier` as \"Supplier:Link/Supplier:120\",\n\t`poi_pri`.`supplier_name` as \"Supplier Name::150\",\n\t`poi_pri`.`item_code` as \"Item Code:Link/Item:120\",\n\t`poi_pri`.`qty` as \"Qty:Float:100\",\n\t`poi_pri`.`base_amount` as \"Base Amount:Currency:100\",\n\t`poi_pri`.`received_qty` as \"Received Qty:Float:100\",\n\t`poi_pri`.`received_amount` as \"Received Qty Amount:Currency:100\",\n\t`poi_pri`.`qty_to_receive` as \"Qty to Receive:Float:100\",\n\t`poi_pri`.`amount_to_be_received` as \"Amount to Receive:Currency:100\",\n\t`poi_pri`.`billed_amount` as \"Billed Amount:Currency:100\",\n\t`poi_pri`.`amount_to_be_billed` as \"Amount To Be Billed:Currency:100\",\n\tSUM(`pii`.`qty`) AS \"Billed Qty:Float:100\",\n\t`poi_pri`.qty - SUM(`pii`.`qty`) AS \"Qty To Be Billed:Float:100\",\n\t`poi_pri`.`warehouse` as \"Warehouse:Link/Warehouse:150\",\n\t`poi_pri`.`item_name` as \"Item Name::150\",\n\t`poi_pri`.`description` as \"Description::200\",\n\t`poi_pri`.`brand` as \"Brand::100\",\n\t`poi_pri`.`project` as \"Project\",\n\t`poi_pri`.`company` as \"Company:Link/Company:\"\nFROM\n\t(SELECT\n\t\t`po`.`name` AS 'purchase_order',\n\t\t`po`.`status`,\n\t\t`po`.`company`,\n\t\t`poi`.`warehouse`,\n\t\t`poi`.`brand`,\n\t\t`poi`.`description`,\n\t\t`po`.`transaction_date`,\n\t\t`poi`.`schedule_date`,\n\t\t`po`.`supplier`,\n\t\t`po`.`supplier_name`,\n\t\t`poi`.`project`,\n\t\t`poi`.`item_code`,\n\t\t`poi`.`item_name`,\n\t\t`poi`.`qty`,\n\t\t`poi`.`base_amount`,\n\t\t`poi`.`received_qty`,\n\t\t(`poi`.billed_amt * ifnull(`po`.conversion_rate, 1)) as billed_amount,\n\t\t(`poi`.base_amount - (`poi`.billed_amt * ifnull(`po`.conversion_rate, 1))) as amount_to_be_billed,\n\t\t`poi`.`qty` - IFNULL(`poi`.`received_qty`, 0) AS 'qty_to_receive',\n\t\t(`poi`.`qty` - IFNULL(`poi`.`received_qty`, 0)) * `poi`.`rate` AS 'amount_to_be_received',\n\t\tSUM(`pri`.`amount`) AS 'received_amount',\n\t\t`poi`.`name` AS 'poi_name',\n\t\t`pri`.`name` AS 'pri_name'\n\tFROM\n\t\t`tabPurchase Order` po\n\t\tLEFT JOIN `tabPurchase Order Item` poi\n\t\tON `poi`.`parent` = `po`.`name`\n\t\tLEFT JOIN `tabPurchase Receipt Item` pri\n\t\tON `pri`.`purchase_order_item` = `poi`.`name`\n\t\t\tAND `pri`.`docstatus`=1\n\tWHERE\n\t\t`po`.`status` not in ('Stopped', 'Closed')\n\t\tAND `po`.`docstatus` = 1\n\t\tAND IFNULL(`poi`.`received_qty`, 0) < IFNULL(`poi`.`qty`, 0)\n\tGROUP BY `poi`.`name`\n\tORDER BY `po`.`transaction_date` ASC\n\t) poi_pri\n\tLEFT JOIN `tabPurchase Invoice Item` pii\n\tON `pii`.`po_detail` = `poi_pri`.`poi_name`\n\t\tAND `pii`.`docstatus`=1\nGROUP BY `poi_pri`.`poi_name`", "query": "SELECT\n\t`poi_pri`.`purchase_order` as \"Purchase Order:Link/Purchase Order:120\",\n\t`poi_pri`.`status` as \"Status:Data:120\",\n\t`poi_pri`.`transaction_date` as \"Date:Date:100\",\n\t`poi_pri`.`schedule_date` as \"Reqd by Date:Date:110\",\n\t`poi_pri`.`supplier` as \"Supplier:Link/Supplier:120\",\n\t`poi_pri`.`supplier_name` as \"Supplier Name::150\",\n\t`poi_pri`.`item_code` as \"Item Code:Link/Item:120\",\n\t`poi_pri`.`qty` as \"Qty:Float:100\",\n\t`poi_pri`.`base_amount` as \"Base Amount:Currency:100\",\n\t`poi_pri`.`received_qty` as \"Received Qty:Float:100\",\n\t`poi_pri`.`received_amount` as \"Received Qty Amount:Currency:100\",\n\t`poi_pri`.`qty_to_receive` as \"Qty to Receive:Float:100\",\n\t`poi_pri`.`amount_to_be_received` as \"Amount to Receive:Currency:100\",\n\t`poi_pri`.`billed_amount` as \"Billed Amount:Currency:100\",\n\t`poi_pri`.`amount_to_be_billed` as \"Amount To Be Billed:Currency:100\",\n\tSUM(`pii`.`qty`) AS \"Billed Qty:Float:100\",\n\t`poi_pri`.qty - SUM(`pii`.`qty`) AS \"Qty To Be Billed:Float:100\",\n\t`poi_pri`.`warehouse` as \"Warehouse:Link/Warehouse:150\",\n\t`poi_pri`.`item_name` as \"Item Name::150\",\n\t`poi_pri`.`description` as \"Description::200\",\n\t`poi_pri`.`brand` as \"Brand::100\",\n\t`poi_pri`.`project` as \"Project\",\n\t`poi_pri`.`company` as \"Company:Link/Company:\"\nFROM\n\t(SELECT\n\t\t`po`.`name` AS 'purchase_order',\n\t\t`po`.`status`,\n\t\t`po`.`company`,\n\t\t`poi`.`warehouse`,\n\t\t`poi`.`brand`,\n\t\t`poi`.`description`,\n\t\t`po`.`transaction_date`,\n\t\t`poi`.`schedule_date`,\n\t\t`po`.`supplier`,\n\t\t`po`.`supplier_name`,\n\t\t`poi`.`project`,\n\t\t`poi`.`item_code`,\n\t\t`poi`.`item_name`,\n\t\t`poi`.`qty`,\n\t\t`poi`.`base_amount`,\n\t\t`poi`.`received_qty`,\n\t\t(`poi`.billed_amt * ifnull(`po`.conversion_rate, 1)) as billed_amount,\n\t\t(`poi`.base_amount - (`poi`.billed_amt * ifnull(`po`.conversion_rate, 1))) as amount_to_be_billed,\n\t\t`poi`.`qty` - IFNULL(`poi`.`received_qty`, 0) AS 'qty_to_receive',\n\t\t(`poi`.`qty` - IFNULL(`poi`.`received_qty`, 0)) * `poi`.`rate` AS 'amount_to_be_received',\n\t\tSUM(`pri`.`amount`) AS 'received_amount',\n\t\t`poi`.`name` AS 'poi_name',\n\t\t`pri`.`name` AS 'pri_name'\n\tFROM\n\t\t`tabPurchase Order` po\n\t\tLEFT JOIN `tabPurchase Order Item` poi\n\t\tON `poi`.`parent` = `po`.`name`\n\t\tLEFT JOIN `tabPurchase Receipt Item` pri\n\t\tON `pri`.`purchase_order_item` = `poi`.`name`\n\t\t\tAND `pri`.`docstatus`=1\n\tWHERE\n\t\t`po`.`status` not in ('Stopped', 'Closed')\n\t\tAND `po`.`docstatus` = 1\n\t\tAND IFNULL(`poi`.`received_qty`, 0) < IFNULL(`poi`.`qty`, 0)\n\tGROUP BY `poi`.`name`\n\tORDER BY `po`.`transaction_date` ASC\n\t) poi_pri\n\tLEFT JOIN `tabPurchase Invoice Item` pii\n\tON `pii`.`po_detail` = `poi_pri`.`poi_name`\n\t\tAND `pii`.`docstatus`=1\nGROUP BY `poi_pri`.`poi_name`",
"ref_doctype": "Purchase Order", "ref_doctype": "Purchase Order",
"report_name": "Purchase Order Items To Be Received or Billed1", "report_name": "Purchase Order Items To Be Received or Billed",
"report_type": "Query Report", "report_type": "Query Report",
"roles": [ "roles": [
{ {

View File

@ -122,8 +122,8 @@ def get_item_details(items, sl_entries, include_uom):
cf_field = cf_join = "" cf_field = cf_join = ""
if include_uom: if include_uom:
cf_field = ", ucd.conversion_factor" cf_field = ", ucd.conversion_factor"
cf_join = "left join `tabUOM Conversion Detail` ucd on ucd.parent=item.name and ucd.uom='%s'" \ cf_join = "left join `tabUOM Conversion Detail` ucd on ucd.parent=item.name and ucd.uom=%s" \
% (include_uom) % frappe.db.escape(include_uom)
res = frappe.db.sql(""" res = frappe.db.sql("""
select select

View File

@ -0,0 +1,57 @@
{
"add_more_button": 1,
"app": "ERPNext",
"creation": "2019-11-15 14:41:12.007359",
"docstatus": 0,
"doctype": "Setup Wizard Slide",
"domains": [],
"help_links": [],
"idx": 0,
"image_src": "/assets/erpnext/images/illustrations/product.png",
"max_count": 3,
"modified": "2019-11-26 18:26:35.305755",
"modified_by": "Administrator",
"name": "Add A Few Products You Buy Or Sell",
"owner": "Administrator",
"ref_doctype": "Item",
"slide_desc": "",
"slide_fields": [
{
"align": "",
"fieldname": "item",
"fieldtype": "Data",
"label": "Item",
"placeholder": "Product Name",
"reqd": 1
},
{
"align": "",
"fieldtype": "Column Break",
"reqd": 1
},
{
"align": "",
"fieldname": "uom",
"fieldtype": "Link",
"label": "UOM",
"options": "UOM",
"reqd": 1
},
{
"align": "",
"fieldtype": "Column Break",
"reqd": 0
},
{
"align": "",
"fieldname": "item_price",
"fieldtype": "Currency",
"label": "Item Price",
"reqd": 1
}
],
"slide_order": 30,
"slide_title": "Add A Few Products You Buy Or Sell",
"slide_type": "Create",
"submit_method": ""
}

View File

@ -1329,7 +1329,7 @@ apps/erpnext/erpnext/hr/doctype/job_offer/job_offer.js,Create Employee,Mitarbeit
apps/erpnext/erpnext/utilities/transaction_base.py,Invalid Posting Time,Ungültige Buchungszeit apps/erpnext/erpnext/utilities/transaction_base.py,Invalid Posting Time,Ungültige Buchungszeit
DocType: Salary Component,Condition and Formula,Zustand und Formel DocType: Salary Component,Condition and Formula,Zustand und Formel
DocType: Lead,Campaign Name,Kampagnenname DocType: Lead,Campaign Name,Kampagnenname
apps/erpnext/erpnext/setup/default_energy_point_rules.py,On Task Completion,Bei Abschluss der Aufgabe apps/erpnext/erpnext/setup/default_energy_point_rules.py,On Task Completion,Bei Abschluss des Vorgangs
apps/erpnext/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.py,There is no leave period in between {0} and {1},Es gibt keinen Urlaub zwischen {0} und {1} apps/erpnext/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.py,There is no leave period in between {0} and {1},Es gibt keinen Urlaub zwischen {0} und {1}
DocType: Fee Validity,Healthcare Practitioner,praktischer Arzt DocType: Fee Validity,Healthcare Practitioner,praktischer Arzt
DocType: Hotel Room,Capacity,Kapazität DocType: Hotel Room,Capacity,Kapazität
@ -1353,7 +1353,7 @@ DocType: Payment Entry,Received Amount (Company Currency),Erhaltene Menge (Gesel
apps/erpnext/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py,Payment Cancelled. Please check your GoCardless Account for more details,Zahlung abgebrochen. Bitte überprüfen Sie Ihr GoCardless Konto für weitere Details apps/erpnext/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py,Payment Cancelled. Please check your GoCardless Account for more details,Zahlung abgebrochen. Bitte überprüfen Sie Ihr GoCardless Konto für weitere Details
DocType: Work Order,Skip Material Transfer to WIP Warehouse,Überspringen Sie die Materialübertragung in das WIP-Lager DocType: Work Order,Skip Material Transfer to WIP Warehouse,Überspringen Sie die Materialübertragung in das WIP-Lager
DocType: Contract,N/A,nicht verfügbar DocType: Contract,N/A,nicht verfügbar
DocType: Task Type,Task Type,Aufgabentyp DocType: Task Type,Task Type,Vorgangstyp
DocType: Topic,Topic Content,Themeninhalt DocType: Topic,Topic Content,Themeninhalt
DocType: Delivery Settings,Send with Attachment,Senden mit Anhang DocType: Delivery Settings,Send with Attachment,Senden mit Anhang
DocType: Service Level,Priorities,Prioritäten DocType: Service Level,Priorities,Prioritäten
@ -2449,7 +2449,7 @@ apps/erpnext/erpnext/public/js/utils/serial_no_batch_selector.js,Please select b
DocType: Asset,Depreciation Schedules,Abschreibungen Termine DocType: Asset,Depreciation Schedules,Abschreibungen Termine
apps/erpnext/erpnext/projects/doctype/timesheet/timesheet.js,Create Sales Invoice,Verkaufsrechnung erstellen apps/erpnext/erpnext/projects/doctype/timesheet/timesheet.js,Create Sales Invoice,Verkaufsrechnung erstellen
apps/erpnext/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.html,Ineligible ITC,Nicht förderfähiges ITC apps/erpnext/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.html,Ineligible ITC,Nicht förderfähiges ITC
DocType: Task,Dependent Tasks,Abhängige Aufgaben DocType: Task,Dependent Tasks,Abhängige Vorgänge
apps/erpnext/erpnext/regional/report/gstr_1/gstr_1.py,Following accounts might be selected in GST Settings:,In den GST-Einstellungen können folgende Konten ausgewählt werden: apps/erpnext/erpnext/regional/report/gstr_1/gstr_1.py,Following accounts might be selected in GST Settings:,In den GST-Einstellungen können folgende Konten ausgewählt werden:
apps/erpnext/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.js,Quantity to Produce,Menge zu produzieren apps/erpnext/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.js,Quantity to Produce,Menge zu produzieren
apps/erpnext/erpnext/hr/doctype/leave_application/leave_application.py,Application period cannot be outside leave allocation period,Beantragter Zeitraum kann nicht außerhalb der beantragten Urlaubszeit liegen apps/erpnext/erpnext/hr/doctype/leave_application/leave_application.py,Application period cannot be outside leave allocation period,Beantragter Zeitraum kann nicht außerhalb der beantragten Urlaubszeit liegen
@ -2846,7 +2846,7 @@ DocType: Loan,Applicant Type,Bewerbertyp
DocType: Purchase Invoice,03-Deficiency in services,03-Mangel an Dienstleistungen DocType: Purchase Invoice,03-Deficiency in services,03-Mangel an Dienstleistungen
DocType: Healthcare Settings,Default Medical Code Standard,Default Medical Code Standard DocType: Healthcare Settings,Default Medical Code Standard,Default Medical Code Standard
DocType: Purchase Invoice Item,HSN/SAC,HSN / SAC DocType: Purchase Invoice Item,HSN/SAC,HSN / SAC
DocType: Project Template Task,Project Template Task,Projektvorlagenaufgabe DocType: Project Template Task,Project Template Task,Projektvorgangsvorlage
DocType: Accounts Settings,Over Billing Allowance (%),Mehr als Abrechnungsbetrag (%) DocType: Accounts Settings,Over Billing Allowance (%),Mehr als Abrechnungsbetrag (%)
apps/erpnext/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py,Purchase Receipt {0} is not submitted,Kaufbeleg {0} wurde nicht übertragen apps/erpnext/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py,Purchase Receipt {0} is not submitted,Kaufbeleg {0} wurde nicht übertragen
DocType: Company,Default Payable Account,Standard-Verbindlichkeitenkonto DocType: Company,Default Payable Account,Standard-Verbindlichkeitenkonto
@ -3323,7 +3323,7 @@ DocType: Soil Texture,Silt,Schlick
,Qty to Order,Zu bestellende Menge ,Qty to Order,Zu bestellende Menge
DocType: Period Closing Voucher,"The account head under Liability or Equity, in which Profit/Loss will be booked","Der Kontenkopf unter Eigen- oder Fremdkapital, in dem Gewinn / Verlust verbucht wird" DocType: Period Closing Voucher,"The account head under Liability or Equity, in which Profit/Loss will be booked","Der Kontenkopf unter Eigen- oder Fremdkapital, in dem Gewinn / Verlust verbucht wird"
apps/erpnext/erpnext/accounts/doctype/budget/budget.py,Another Budget record '{0}' already exists against {1} '{2}' and account '{3}' for fiscal year {4},Ein weiterer Budgeteintrag &#39;{0}&#39; existiert bereits für {1} &#39;{2}&#39; und für &#39;{3}&#39; für das Geschäftsjahr {4} apps/erpnext/erpnext/accounts/doctype/budget/budget.py,Another Budget record '{0}' already exists against {1} '{2}' and account '{3}' for fiscal year {4},Ein weiterer Budgeteintrag &#39;{0}&#39; existiert bereits für {1} &#39;{2}&#39; und für &#39;{3}&#39; für das Geschäftsjahr {4}
apps/erpnext/erpnext/config/projects.py,Gantt chart of all tasks.,Gantt-Diagramm aller Aufgaben apps/erpnext/erpnext/config/projects.py,Gantt chart of all tasks.,Gantt-Diagramm aller Vorgänge
DocType: Opportunity,Mins to First Response,Minuten zum First Response DocType: Opportunity,Mins to First Response,Minuten zum First Response
DocType: Pricing Rule,Margin Type,Margenart DocType: Pricing Rule,Margin Type,Margenart
apps/erpnext/erpnext/projects/doctype/project/project_dashboard.html,{0} hours,{0} Stunden apps/erpnext/erpnext/projects/doctype/project/project_dashboard.html,{0} hours,{0} Stunden
@ -3961,7 +3961,7 @@ apps/erpnext/erpnext/selling/doctype/sales_order/sales_order.py,Maintenance Sche
apps/erpnext/erpnext/education/doctype/student/student_dashboard.py,Student LMS Activity,Student LMS Aktivität apps/erpnext/erpnext/education/doctype/student/student_dashboard.py,Student LMS Activity,Student LMS Aktivität
DocType: POS Profile,Applicable for Users,Anwendbar für Benutzer DocType: POS Profile,Applicable for Users,Anwendbar für Benutzer
DocType: Supplier Quotation,PUR-SQTN-.YYYY.-,PUR-SQTN-.JJJJ.- DocType: Supplier Quotation,PUR-SQTN-.YYYY.-,PUR-SQTN-.JJJJ.-
apps/erpnext/erpnext/projects/doctype/project/project.js,Set Project and all Tasks to status {0}?,Projekt und alle Aufgaben auf Status {0} setzen? apps/erpnext/erpnext/projects/doctype/project/project.js,Set Project and all Tasks to status {0}?,Projekt und alle Vorgänge auf Status {0} setzen?
DocType: Purchase Invoice,Set Advances and Allocate (FIFO),Vorschüsse setzen und zuordnen (FIFO) DocType: Purchase Invoice,Set Advances and Allocate (FIFO),Vorschüsse setzen und zuordnen (FIFO)
apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.py,No Work Orders created,Keine Arbeitsaufträge erstellt apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.py,No Work Orders created,Keine Arbeitsaufträge erstellt
apps/erpnext/erpnext/hr/doctype/salary_slip/salary_slip.py,Salary Slip of employee {0} already created for this period,Gehaltsabrechnung der Mitarbeiter {0} für diesen Zeitraum bereits erstellt apps/erpnext/erpnext/hr/doctype/salary_slip/salary_slip.py,Salary Slip of employee {0} already created for this period,Gehaltsabrechnung der Mitarbeiter {0} für diesen Zeitraum bereits erstellt
@ -4418,7 +4418,7 @@ DocType: Normal Test Items,Result Value,Ergebnis Wert
DocType: Hotel Room,Hotels,Hotels DocType: Hotel Room,Hotels,Hotels
apps/erpnext/erpnext/accounts/doctype/cost_center/cost_center_tree.js,New Cost Center Name,Neuer Kostenstellenname apps/erpnext/erpnext/accounts/doctype/cost_center/cost_center_tree.js,New Cost Center Name,Neuer Kostenstellenname
DocType: Leave Control Panel,Leave Control Panel,Urlaubsverwaltung DocType: Leave Control Panel,Leave Control Panel,Urlaubsverwaltung
DocType: Project,Task Completion,Aufgabenerledigung DocType: Project,Task Completion,Vorgangserfüllung
apps/erpnext/erpnext/templates/generators/item/item_add_to_cart.html,Not in Stock,Nicht lagernd apps/erpnext/erpnext/templates/generators/item/item_add_to_cart.html,Not in Stock,Nicht lagernd
DocType: Volunteer,Volunteer Skills,Freiwillige Fähigkeiten DocType: Volunteer,Volunteer Skills,Freiwillige Fähigkeiten
DocType: Additional Salary,HR User,Nutzer Personalabteilung DocType: Additional Salary,HR User,Nutzer Personalabteilung
@ -5197,7 +5197,7 @@ DocType: Work Order,Material Transferred for Manufacturing,Material zur Herstell
apps/erpnext/erpnext/accounts/report/general_ledger/general_ledger.py,Account {0} does not exists,Konto {0} existiert nicht apps/erpnext/erpnext/accounts/report/general_ledger/general_ledger.py,Account {0} does not exists,Konto {0} existiert nicht
apps/erpnext/erpnext/accounts/doctype/sales_invoice/sales_invoice.js,Select Loyalty Program,Wählen Sie Treueprogramm apps/erpnext/erpnext/accounts/doctype/sales_invoice/sales_invoice.js,Select Loyalty Program,Wählen Sie Treueprogramm
DocType: Project,Project Type,Projekttyp DocType: Project,Project Type,Projekttyp
apps/erpnext/erpnext/projects/doctype/task/task.py,Child Task exists for this Task. You can not delete this Task.,Für diese Aufgabe existiert eine untergeordnete Aufgabe. Sie können diese Aufgabe daher nicht löschen. apps/erpnext/erpnext/projects/doctype/task/task.py,Child Task exists for this Task. You can not delete this Task.,Für diesen Vorgang existiert ein untergeordneter Vorgang. Sie können diese Aufgabe daher nicht löschen.
apps/erpnext/erpnext/setup/doctype/sales_person/sales_person.py,Either target qty or target amount is mandatory.,Entweder Zielstückzahl oder Zielmenge ist zwingend erforderlich. apps/erpnext/erpnext/setup/doctype/sales_person/sales_person.py,Either target qty or target amount is mandatory.,Entweder Zielstückzahl oder Zielmenge ist zwingend erforderlich.
apps/erpnext/erpnext/config/projects.py,Cost of various activities,Aufwendungen für verschiedene Tätigkeiten apps/erpnext/erpnext/config/projects.py,Cost of various activities,Aufwendungen für verschiedene Tätigkeiten
apps/erpnext/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py,"Setting Events to {0}, since the Employee attached to the below Sales Persons does not have a User ID{1}","Einstellen Events auf {0}, da die Mitarbeiter auf die beigefügten unter Verkaufs Personen keine Benutzer-ID {1}" apps/erpnext/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py,"Setting Events to {0}, since the Employee attached to the below Sales Persons does not have a User ID{1}","Einstellen Events auf {0}, da die Mitarbeiter auf die beigefügten unter Verkaufs Personen keine Benutzer-ID {1}"
@ -5597,7 +5597,7 @@ apps/erpnext/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py,Paid
apps/erpnext/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py,{0} is not a valid Batch Number for Item {1},{0} ist keine gültige Chargennummer für Artikel {1} apps/erpnext/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py,{0} is not a valid Batch Number for Item {1},{0} ist keine gültige Chargennummer für Artikel {1}
apps/erpnext/erpnext/shopping_cart/cart.py,Please enter valid coupon code !!,Bitte geben Sie einen gültigen Gutscheincode ein !! apps/erpnext/erpnext/shopping_cart/cart.py,Please enter valid coupon code !!,Bitte geben Sie einen gültigen Gutscheincode ein !!
apps/erpnext/erpnext/hr/doctype/leave_application/leave_application.py,Note: There is not enough leave balance for Leave Type {0},Hinweis: Es gibt nicht genügend Urlaubsguthaben für Abwesenheitstyp {0} apps/erpnext/erpnext/hr/doctype/leave_application/leave_application.py,Note: There is not enough leave balance for Leave Type {0},Hinweis: Es gibt nicht genügend Urlaubsguthaben für Abwesenheitstyp {0}
DocType: Task,Task Description,Aufgabenbeschreibung DocType: Task,Task Description,Vorgangsbeschreibung
DocType: Training Event,Seminar,Seminar DocType: Training Event,Seminar,Seminar
DocType: Program Enrollment Fee,Program Enrollment Fee,Programm Einschreibegebühr DocType: Program Enrollment Fee,Program Enrollment Fee,Programm Einschreibegebühr
DocType: Item,Supplier Items,Lieferantenartikel DocType: Item,Supplier Items,Lieferantenartikel
@ -5754,7 +5754,7 @@ apps/erpnext/erpnext/accounts/doctype/sales_invoice/pos.py,All Territories,Alle
DocType: Lost Reason Detail,Lost Reason Detail,Verlorene Begründung Detail DocType: Lost Reason Detail,Lost Reason Detail,Verlorene Begründung Detail
apps/erpnext/erpnext/hr/utils.py,Please set leave policy for employee {0} in Employee / Grade record,Legen Sie die Abwesenheitsrichtlinie für den Mitarbeiter {0} im Mitarbeiter- / Notensatz fest apps/erpnext/erpnext/hr/utils.py,Please set leave policy for employee {0} in Employee / Grade record,Legen Sie die Abwesenheitsrichtlinie für den Mitarbeiter {0} im Mitarbeiter- / Notensatz fest
apps/erpnext/erpnext/public/js/controllers/transaction.js,Invalid Blanket Order for the selected Customer and Item,Ungültiger Blankoauftrag für den ausgewählten Kunden und Artikel apps/erpnext/erpnext/public/js/controllers/transaction.js,Invalid Blanket Order for the selected Customer and Item,Ungültiger Blankoauftrag für den ausgewählten Kunden und Artikel
apps/erpnext/erpnext/projects/doctype/task/task_tree.js,Add Multiple Tasks,Mehrere Aufgaben hinzufügen apps/erpnext/erpnext/projects/doctype/task/task_tree.js,Add Multiple Tasks,Mehrere Vorgänge hinzufügen
DocType: Purchase Invoice,Items,Artikel DocType: Purchase Invoice,Items,Artikel
apps/erpnext/erpnext/crm/doctype/contract/contract.py,End Date cannot be before Start Date.,Das Enddatum darf nicht vor dem Startdatum liegen. apps/erpnext/erpnext/crm/doctype/contract/contract.py,End Date cannot be before Start Date.,Das Enddatum darf nicht vor dem Startdatum liegen.
apps/erpnext/erpnext/education/doctype/course_enrollment/course_enrollment.py,Student is already enrolled.,Student ist bereits eingetragen sind. apps/erpnext/erpnext/education/doctype/course_enrollment/course_enrollment.py,Student is already enrolled.,Student ist bereits eingetragen sind.

Can't render this file because it is too large.

View File

@ -1,287 +0,0 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe, erpnext
from frappe import _
from erpnext.setup.doctype.setup_progress.setup_progress import get_action_completed_state
def get_slide_settings():
defaults = frappe.defaults.get_defaults()
domain = frappe.get_cached_value('Company', erpnext.get_default_company(), 'domain')
company = defaults.get("company") or ''
currency = defaults.get("currency") or ''
doc = frappe.get_doc("Setup Progress")
item = [d for d in doc.get("actions") if d.action_name == "Set Sales Target"]
if len(item):
item = item[0]
if not item.action_document:
item.action_document = company
doc.save()
# Initial state of slides
return [
frappe._dict(
action_name='Add Company',
title=_("Setup Company") if domain != 'Education' else _("Setup Institution"),
help=_('Setup your ' + ('company' if domain != 'Education' else 'institution') + ' and brand.'),
# image_src="/assets/erpnext/images/illustrations/shop.jpg",
fields=[],
done_state_title=_("You added " + company),
done_state_title_route=["Form", "Company", company],
help_links=[
{
"label": _("Chart of Accounts"),
"url": ["https://erpnext.com/docs/user/manual/en/accounts/chart-of-accounts"]
},
{
"label": _("Opening Balances"),
"video_id": "U5wPIvEn-0c"
}
]
),
frappe._dict(
action_name='Set Sales Target',
domains=('Manufacturing', 'Services', 'Retail', 'Distribution'),
title=_("Set a Target"),
help=_("Set a sales goal you'd like to achieve for your company."),
fields=[
{"fieldtype":"Currency", "fieldname":"monthly_sales_target",
"label":_("Monthly Sales Target (" + currency + ")"), "reqd":1},
],
submit_method="erpnext.utilities.user_progress_utils.set_sales_target",
done_state_title=_("Go to " + company),
done_state_title_route=["Form", "Company", company],
help_links=[
{
"label": _('Learn More'),
"url": ["https://erpnext.com/docs/user/manual/en/setting-up/setting-company-sales-goal"]
}
]
),
frappe._dict(
action_name='Add Customers',
domains=('Manufacturing', 'Services', 'Retail', 'Distribution'),
title=_("Add Customers"),
help=_("List a few of your customers. They could be organizations or individuals."),
fields=[
{"fieldtype":"Section Break"},
{"fieldtype":"Data", "fieldname":"customer", "label":_("Customer"),
"placeholder":_("Customer Name")},
{"fieldtype":"Column Break"},
{"fieldtype":"Data", "fieldname":"customer_contact",
"label":_("Contact Name"), "placeholder":_("Contact Name")}
],
add_more=1, max_count=3, mandatory_entry=1,
submit_method="erpnext.utilities.user_progress_utils.create_customers",
done_state_title=_("Go to Customers"),
done_state_title_route=["List", "Customer"],
help_links=[
{
"label": _('Learn More'),
"url": ["https://erpnext.com/docs/user/manual/en/CRM/customer.html"]
}
]
),
frappe._dict(
action_name='Add Letterhead',
domains=('Manufacturing', 'Services', 'Retail', 'Distribution', 'Education'),
title=_("Add Letterhead"),
help=_("Upload your letter head (Keep it web friendly as 900px by 100px)"),
fields=[
{"fieldtype":"Attach Image", "fieldname":"letterhead",
"is_private": 0,
"align": "center"
},
],
mandatory_entry=1,
submit_method="erpnext.utilities.user_progress_utils.create_letterhead",
done_state_title=_("Go to Letterheads"),
done_state_title_route=["List", "Letter Head"]
),
frappe._dict(
action_name='Add Suppliers',
domains=('Manufacturing', 'Services', 'Retail', 'Distribution'),
icon="fa fa-group",
title=_("Your Suppliers"),
help=_("List a few of your suppliers. They could be organizations or individuals."),
fields=[
{"fieldtype":"Section Break"},
{"fieldtype":"Data", "fieldname":"supplier", "label":_("Supplier"),
"placeholder":_("Supplier Name")},
{"fieldtype":"Column Break"},
{"fieldtype":"Data", "fieldname":"supplier_contact",
"label":_("Contact Name"), "placeholder":_("Contact Name")},
],
add_more=1, max_count=3, mandatory_entry=1,
submit_method="erpnext.utilities.user_progress_utils.create_suppliers",
done_state_title=_("Go to Suppliers"),
done_state_title_route=["List", "Supplier"],
help_links=[
{
"label": _('Learn More'),
"url": ["https://erpnext.com/docs/user/manual/en/buying/supplier"]
},
{
"label": _('Customers and Suppliers'),
"video_id": "zsrrVDk6VBs"
},
]
),
frappe._dict(
action_name='Add Products',
domains=['Manufacturing', 'Services', 'Retail', 'Distribution'],
icon="fa fa-barcode",
title=_("Your Products or Services"),
help=_("List your products or services that you buy or sell."),
fields=[
{"fieldtype":"Section Break", "show_section_border": 1},
{"fieldtype":"Data", "fieldname":"item", "label":_("Item"),
"placeholder":_("A Product")},
{"fieldtype":"Column Break"},
{"fieldtype":"Select", "fieldname":"item_uom", "label":_("UOM"),
"options":[_("Unit"), _("Nos"), _("Box"), _("Pair"), _("Kg"), _("Set"),
_("Hour"), _("Minute"), _("Litre"), _("Meter"), _("Gram")],
"default": _("Unit"), "static": 1},
{"fieldtype":"Column Break"},
{"fieldtype":"Currency", "fieldname":"item_price", "label":_("Rate"), "static": 1}
],
add_more=1, max_count=3, mandatory_entry=1,
submit_method="erpnext.utilities.user_progress_utils.create_items",
done_state_title=_("Go to Items"),
done_state_title_route=["List", "Item"],
help_links=[
{
"label": _("Explore Sales Cycle"),
"video_id": "1eP90MWoDQM"
},
]
),
# Education slides begin
frappe._dict(
action_name='Add Programs',
domains=("Education"),
title=_("Program"),
help=_("Example: Masters in Computer Science"),
fields=[
{"fieldtype":"Section Break", "show_section_border": 1},
{"fieldtype":"Data", "fieldname":"program", "label":_("Program"), "placeholder": _("Program Name")},
],
add_more=1, max_count=3, mandatory_entry=1,
submit_method="erpnext.utilities.user_progress_utils.create_program",
done_state_title=_("Go to Programs"),
done_state_title_route=["List", "Program"],
help_links=[
{
"label": _("Student Application"),
"video_id": "l8PUACusN3E"
},
]
),
frappe._dict(
action_name='Add Courses',
domains=["Education"],
title=_("Course"),
help=_("Example: Basic Mathematics"),
fields=[
{"fieldtype":"Section Break", "show_section_border": 1},
{"fieldtype":"Data", "fieldname":"course", "label":_("Course"), "placeholder": _("Course Name")},
],
add_more=1, max_count=3, mandatory_entry=1,
submit_method="erpnext.utilities.user_progress_utils.create_course",
done_state_title=_("Go to Courses"),
done_state_title_route=["List", "Course"],
help_links=[
{
"label": _('Add Students'),
"route": ["List", "Student"]
}
]
),
frappe._dict(
action_name='Add Instructors',
domains=["Education"],
title=_("Instructor"),
help=_("People who teach at your organisation"),
fields=[
{"fieldtype":"Section Break", "show_section_border": 1},
{"fieldtype":"Data", "fieldname":"instructor", "label":_("Instructor"), "placeholder": _("Instructor Name")},
],
add_more=1, max_count=3, mandatory_entry=1,
submit_method="erpnext.utilities.user_progress_utils.create_instructor",
done_state_title=_("Go to Instructors"),
done_state_title_route=["List", "Instructor"],
help_links=[
{
"label": _('Student Batches'),
"route": ["List", "Student Batch"]
}
]
),
frappe._dict(
action_name='Add Rooms',
domains=["Education"],
title=_("Room"),
help=_("Classrooms/ Laboratories etc where lectures can be scheduled."),
fields=[
{"fieldtype":"Section Break", "show_section_border": 1},
{"fieldtype":"Data", "fieldname":"room", "label":_("Room")},
{"fieldtype":"Column Break"},
{"fieldtype":"Int", "fieldname":"room_capacity", "label":_("Room Capacity"), "static": 1},
],
add_more=1, max_count=3, mandatory_entry=1,
submit_method="erpnext.utilities.user_progress_utils.create_room",
done_state_title=_("Go to Rooms"),
done_state_title_route=["List", "Room"],
help_links=[]
),
# Education slides end
frappe._dict(
action_name='Add Users',
title=_("Add Users"),
help=_("Add users to your organization, other than yourself."),
fields=[
{"fieldtype":"Section Break"},
{"fieldtype":"Data", "fieldname":"user_email", "label":_("Email ID"),
"placeholder":_("user@example.com"), "options": "Email", "static": 1},
{"fieldtype":"Column Break"},
{"fieldtype":"Data", "fieldname":"user_fullname",
"label":_("Full Name"), "static": 1},
],
add_more=1, max_count=3, mandatory_entry=1,
submit_method="erpnext.utilities.user_progress_utils.create_users",
done_state_title=_("Go to Users"),
done_state_title_route=["List", "User"],
help_links=[
{
"label": _('Learn More'),
"url": ["https://erpnext.com/docs/user/manual/en/setting-up/users-and-permissions"]
},
{
"label": _('Users and Permissions'),
"video_id": "8Slw1hsTmUI"
},
]
)
]
def get_user_progress_slides():
slides = []
slide_settings = get_slide_settings()
domains = frappe.get_active_domains()
for s in slide_settings:
if not s.domains or any(d in domains for d in s.domains):
s.mark_as_done_method = "erpnext.setup.doctype.setup_progress.setup_progress.set_action_completed_state"
s.done = get_action_completed_state(s.action_name) or 0
slides.append(s)
return slides

View File

@ -1,240 +0,0 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe, erpnext
import json
from frappe import _
from frappe.utils import flt
from erpnext.setup.doctype.setup_progress.setup_progress import update_domain_actions, get_domain_actions_state
@frappe.whitelist()
def set_sales_target(args_data):
args = json.loads(args_data)
defaults = frappe.defaults.get_defaults()
frappe.db.set_value("Company", defaults.get("company"), "monthly_sales_target", args.get('monthly_sales_target'))
@frappe.whitelist()
def create_customers(args_data):
args = json.loads(args_data)
defaults = frappe.defaults.get_defaults()
for i in range(1,4):
customer = args.get("customer_" + str(i))
if customer:
try:
doc = frappe.get_doc({
"doctype":"Customer",
"customer_name": customer,
"customer_type": "Company",
"customer_group": _("Commercial"),
"territory": defaults.get("country"),
"company": defaults.get("company")
}).insert()
if args.get("customer_contact_" + str(i)):
create_contact(args.get("customer_contact_" + str(i)),
"Customer", doc.name)
except frappe.NameError:
pass
@frappe.whitelist()
def create_letterhead(args_data):
args = json.loads(args_data)
letterhead = args.get("letterhead")
if letterhead:
try:
frappe.get_doc({
"doctype":"Letter Head",
"content":"""<div><img src="{0}" style='max-width: 100%%;'><br></div>""".format(letterhead.encode('utf-8')),
"letter_head_name": _("Standard"),
"is_default": 1
}).insert()
except frappe.NameError:
pass
@frappe.whitelist()
def create_suppliers(args_data):
args = json.loads(args_data)
defaults = frappe.defaults.get_defaults()
for i in range(1,4):
supplier = args.get("supplier_" + str(i))
if supplier:
try:
doc = frappe.get_doc({
"doctype":"Supplier",
"supplier_name": supplier,
"supplier_group": _("Local"),
"company": defaults.get("company")
}).insert()
if args.get("supplier_contact_" + str(i)):
create_contact(args.get("supplier_contact_" + str(i)),
"Supplier", doc.name)
except frappe.NameError:
pass
def create_contact(contact, party_type, party):
"""Create contact based on given contact name"""
contact = contact .split(" ")
contact = frappe.get_doc({
"doctype":"Contact",
"first_name":contact[0],
"last_name": len(contact) > 1 and contact[1] or ""
})
contact.append('links', dict(link_doctype=party_type, link_name=party))
contact.insert()
@frappe.whitelist()
def create_items(args_data):
args = json.loads(args_data)
defaults = frappe.defaults.get_defaults()
for i in range(1,4):
item = args.get("item_" + str(i))
if item:
default_warehouse = ""
default_warehouse = frappe.db.get_value("Warehouse", filters={
"warehouse_name": _("Finished Goods"),
"company": defaults.get("company_name")
})
try:
frappe.get_doc({
"doctype":"Item",
"item_code": item,
"item_name": item,
"description": item,
"show_in_website": 1,
"is_sales_item": 1,
"is_purchase_item": 1,
"is_stock_item": 1,
"item_group": _("Products"),
"stock_uom": _(args.get("item_uom_" + str(i))),
"item_defaults": [{
"default_warehouse": default_warehouse,
"company": defaults.get("company_name")
}]
}).insert()
except frappe.NameError:
pass
else:
if args.get("item_price_" + str(i)):
item_price = flt(args.get("item_price_" + str(i)))
price_list_name = frappe.db.get_value("Price List", {"selling": 1})
make_item_price(item, price_list_name, item_price)
price_list_name = frappe.db.get_value("Price List", {"buying": 1})
make_item_price(item, price_list_name, item_price)
def make_item_price(item, price_list_name, item_price):
frappe.get_doc({
"doctype": "Item Price",
"price_list": price_list_name,
"item_code": item,
"price_list_rate": item_price
}).insert()
# Education
@frappe.whitelist()
def create_program(args_data):
args = json.loads(args_data)
for i in range(1,4):
if args.get("program_" + str(i)):
program = frappe.new_doc("Program")
program.program_code = args.get("program_" + str(i))
program.program_name = args.get("program_" + str(i))
try:
program.save()
except frappe.DuplicateEntryError:
pass
@frappe.whitelist()
def create_course(args_data):
args = json.loads(args_data)
for i in range(1,4):
if args.get("course_" + str(i)):
course = frappe.new_doc("Course")
course.course_code = args.get("course_" + str(i))
course.course_name = args.get("course_" + str(i))
try:
course.save()
except frappe.DuplicateEntryError:
pass
@frappe.whitelist()
def create_instructor(args_data):
args = json.loads(args_data)
for i in range(1,4):
if args.get("instructor_" + str(i)):
instructor = frappe.new_doc("Instructor")
instructor.instructor_name = args.get("instructor_" + str(i))
try:
instructor.save()
except frappe.DuplicateEntryError:
pass
@frappe.whitelist()
def create_room(args_data):
args = json.loads(args_data)
for i in range(1,4):
if args.get("room_" + str(i)):
room = frappe.new_doc("Room")
room.room_name = args.get("room_" + str(i))
room.seating_capacity = args.get("room_capacity_" + str(i))
try:
room.save()
except frappe.DuplicateEntryError:
pass
@frappe.whitelist()
def create_users(args_data):
if frappe.session.user == 'Administrator':
return
args = json.loads(args_data)
defaults = frappe.defaults.get_defaults()
for i in range(1,4):
email = args.get("user_email_" + str(i))
fullname = args.get("user_fullname_" + str(i))
if email:
if not fullname:
fullname = email.split("@")[0]
parts = fullname.split(" ", 1)
user = frappe.get_doc({
"doctype": "User",
"email": email,
"first_name": parts[0],
"last_name": parts[1] if len(parts) > 1 else "",
"enabled": 1,
"user_type": "System User"
})
# default roles
user.append_roles("Projects User", "Stock User", "Support Team")
user.flags.delay_emails = True
if not frappe.db.get_value("User", email):
user.insert(ignore_permissions=True)
# create employee
emp = frappe.get_doc({
"doctype": "Employee",
"employee_name": fullname,
"user_id": email,
"status": "Active",
"company": defaults.get("company")
})
emp.flags.ignore_mandatory = True
emp.insert(ignore_permissions = True)
# Ennumerate the setup hooks you're going to need, apart from the slides
@frappe.whitelist()
def update_default_domain_actions_and_get_state():
domain = frappe.get_cached_value('Company', erpnext.get_default_company(), 'domain')
update_domain_actions(domain)
return get_domain_actions_state(domain)