Merge pull request #9435 from rmehta/gst

GST (India) Setup and Invoices #8711
This commit is contained in:
Makarand Bauskar 2017-06-27 11:44:33 +05:30 committed by GitHub
commit 5d8803b23e
69 changed files with 51706 additions and 309 deletions

View File

@ -502,8 +502,20 @@ frappe.ui.form.on('Sales Invoice', {
}
}
}
frm.set_query('company_address', function(doc) {
if(!doc.company) {
frappe.throw(_('Please set Company'));
}
return {
query: 'frappe.contacts.doctype.address.address.address_query',
filters: {
link_doctype: 'Company',
link_name: doc.company
}
};
});
},
project: function(frm){

View File

@ -940,22 +940,22 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "",
"fieldname": "customer_group",
"fieldname": "company_address",
"fieldtype": "Link",
"hidden": 1,
"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": "Customer Group",
"label": "Company Address",
"length": 0,
"no_copy": 0,
"options": "Customer Group",
"options": "Address",
"permlevel": 0,
"print_hide": 1,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
@ -3489,6 +3489,37 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "",
"fieldname": "customer_group",
"fieldtype": "Link",
"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": "Customer Group",
"length": 0,
"no_copy": 0,
"options": "Customer Group",
"permlevel": 0,
"print_hide": 1,
"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,
@ -4596,7 +4627,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2017-06-16 17:07:55.483734",
"modified": "2017-06-22 14:45:35.257640",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",

View File

@ -7,11 +7,12 @@ import frappe
import datetime
from frappe import _, msgprint, scrub
from frappe.defaults import get_user_permissions
from frappe.model.utils import get_fetch_values
from frappe.utils import add_days, getdate, formatdate, get_first_day, date_diff, \
add_years, get_timestamp, nowdate, flt
from frappe.contacts.doctype.address.address import get_address_display, get_default_address
from frappe.contacts.doctype.contact.contact import get_contact_details, get_default_contact
from erpnext.exceptions import PartyFrozen, InvalidCurrency, PartyDisabled, InvalidAccountCurrency
from erpnext.exceptions import PartyFrozen, PartyDisabled, InvalidAccountCurrency
from erpnext.accounts.utils import get_fiscal_year
from erpnext import get_default_currency
@ -42,7 +43,7 @@ def _get_party_details(party=None, account=None, party_type="Customer", company=
party = frappe.get_doc(party_type, party)
set_address_details(out, party, party_type)
set_address_details(out, party, party_type, doctype, company)
set_contact_details(out, party, party_type)
set_other_values(out, party, party_type)
set_price_list(out, party, party_type, price_list)
@ -60,10 +61,11 @@ def _get_party_details(party=None, account=None, party_type="Customer", company=
return out
def set_address_details(out, party, party_type):
def set_address_details(out, party, party_type, doctype=None, company=None):
billing_address_field = "customer_address" if party_type == "Lead" \
else party_type.lower() + "_address"
out[billing_address_field] = get_default_address(party_type, party.name)
out.update(get_fetch_values(doctype, billing_address_field, out[billing_address_field]))
# address display
out.address_display = get_address_display(out[billing_address_field])
@ -72,6 +74,11 @@ def set_address_details(out, party, party_type):
if party_type in ["Customer", "Lead"]:
out.shipping_address_name = get_default_address(party_type, party.name, 'is_shipping_address')
out.shipping_address = get_address_display(out["shipping_address_name"])
out.update(get_fetch_values(doctype, 'shipping_address_name', out.shipping_address_name))
if doctype and doctype in ['Sales Invoice']:
out.company_address = get_default_address('Company', company)
out.update(get_fetch_values(doctype, 'company_address', out.company_address))
def set_contact_details(out, party, party_type):
out.contact_person = get_default_contact(party_type, party.name)
@ -363,28 +370,28 @@ def get_timeline_data(doctype, name):
out.update({ timestamp: count })
return out
def get_dashboard_info(party_type, party):
current_fiscal_year = get_fiscal_year(nowdate(), as_dict=True)
company = frappe.db.get_default("company") or frappe.get_all("Company")[0].name
party_account_currency = get_party_account_currency(party_type, party, company)
company_default_currency = get_default_currency() \
or frappe.db.get_value('Company', company, 'default_currency')
if party_account_currency==company_default_currency:
total_field = "base_grand_total"
else:
total_field = "grand_total"
doctype = "Sales Invoice" if party_type=="Customer" else "Purchase Invoice"
billing_this_year = frappe.db.sql("""
select sum({0})
from `tab{1}`
where {2}=%s and docstatus=1 and posting_date between %s and %s
""".format(total_field, doctype, party_type.lower()),
""".format(total_field, doctype, party_type.lower()),
(party, current_fiscal_year.year_start_date, current_fiscal_year.year_end_date))
total_unpaid = frappe.db.sql("""
select sum(debit_in_account_currency) - sum(credit_in_account_currency)
from `tabGL Entry`
@ -396,5 +403,5 @@ def get_dashboard_info(party_type, party):
info["total_unpaid"] = flt(total_unpaid[0][0]) if total_unpaid else 0
if party_type == "Supplier":
info["total_unpaid"] = -1 * info["total_unpaid"]
return info

View File

@ -7,11 +7,14 @@ from frappe import _
from frappe.utils import flt
def execute(filters=None):
return _execute(filters)
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
if not filters: filters = {}
columns = get_columns()
columns = get_columns(additional_table_columns)
last_col = len(columns)
item_list = get_items(filters)
item_list = get_items(filters, additional_query_columns)
aii_account_map = get_aii_accounts()
if item_list:
item_row_tax, tax_accounts = get_tax_accounts(item_list, columns)
@ -23,7 +26,7 @@ def execute(filters=None):
"width": 80
})
company_currency = frappe.db.get_value("Company", filters.company, "default_currency")
data = []
for d in item_list:
purchase_receipt = None
@ -35,8 +38,16 @@ def execute(filters=None):
expense_account = d.expense_account or aii_account_map.get(d.company)
row = [d.item_code, d.item_name, d.item_group, d.parent, d.posting_date, d.supplier,
d.supplier_name, d.credit_to, d.mode_of_payment, d.project, d.company, d.purchase_order,
purchase_receipt, expense_account, d.qty, d.base_net_rate, d.base_net_amount]
d.supplier_name]
if additional_query_columns:
for col in additional_query_columns:
row.append(d.get(col))
row += [
d.credit_to, d.mode_of_payment, d.project, d.company, d.purchase_order,
purchase_receipt, expense_account, d.qty, d.base_net_rate, d.base_net_amount
]
for tax in tax_accounts:
row.append(item_row_tax.get(d.name, {}).get(tax, 0))
@ -49,17 +60,27 @@ def execute(filters=None):
return columns, data
def get_columns():
return [_("Item Code") + ":Link/Item:120", _("Item Name") + "::120",
def get_columns(additional_table_columns):
columns = [
_("Item Code") + ":Link/Item:120", _("Item Name") + "::120",
_("Item Group") + ":Link/Item Group:100", _("Invoice") + ":Link/Purchase Invoice:120",
_("Posting Date") + ":Date:80", _("Supplier") + ":Link/Supplier:120",
"Supplier Name::120", "Payable Account:Link/Account:120",
"Supplier Name::120"
]
if additional_table_columns:
columns += additional_table_columns
columns += [
"Payable Account:Link/Account:120",
_("Mode of Payment") + ":Link/Mode of Payment:80", _("Project") + ":Link/Project:80",
_("Company") + ":Link/Company:100", _("Purchase Order") + ":Link/Purchase Order:100",
_("Purchase Receipt") + ":Link/Purchase Receipt:100", _("Expense Account") + ":Link/Account:140",
_("Qty") + ":Float:120", _("Rate") + ":Currency/currency:120", _("Amount") + ":Currency/currency:120"
]
return columns
def get_conditions(filters):
conditions = ""
@ -74,21 +95,23 @@ def get_conditions(filters):
return conditions
def get_items(filters):
def get_items(filters, additional_query_columns):
conditions = get_conditions(filters)
match_conditions = frappe.build_match_conditions("Purchase Invoice")
if additional_query_columns:
additional_query_columns = ', ' + ', '.join(additional_query_columns)
return frappe.db.sql("""
select
select
pi_item.name, pi_item.parent, pi.posting_date, pi.credit_to, pi.company,
pi.supplier, pi.remarks, pi.base_net_total, pi_item.item_code, pi_item.item_name,
pi_item.item_group, pi_item.project, pi_item.purchase_order, pi_item.purchase_receipt,
pi_item.po_detail, pi_item.expense_account, pi_item.qty, pi_item.base_net_rate,
pi_item.base_net_amount, pi.supplier_name, pi.mode_of_payment
pi.supplier, pi.remarks, pi.base_net_total, pi_item.item_code, pi_item.item_name,
pi_item.item_group, pi_item.project, pi_item.purchase_order, pi_item.purchase_receipt,
pi_item.po_detail, pi_item.expense_account, pi_item.qty, pi_item.base_net_rate,
pi_item.base_net_amount, pi.supplier_name, pi.mode_of_payment {0}
from `tabPurchase Invoice` pi, `tabPurchase Invoice Item` pi_item
where pi.name = pi_item.parent and pi.docstatus = 1 %s %s
order by pi.posting_date desc, pi_item.item_code desc
""" % (conditions, match_conditions), filters, as_dict=1)
""".format(additional_query_columns) % (conditions, match_conditions), filters, as_dict=1)
def get_aii_accounts():
return dict(frappe.db.sql("select name, stock_received_but_not_billed from tabCompany"))
@ -104,11 +127,11 @@ def get_tax_accounts(item_list, columns):
item_row_map.setdefault(d.parent, {}).setdefault(d.item_code, []).append(d)
tax_details = frappe.db.sql("""
select
select
parent, account_head, item_wise_tax_detail, charge_type, base_tax_amount_after_discount_amount
from `tabPurchase Taxes and Charges`
where parenttype = 'Purchase Invoice' and docstatus = 1
and (account_head is not null and account_head != '')
from `tabPurchase Taxes and Charges`
where parenttype = 'Purchase Invoice' and docstatus = 1
and (account_head is not null and account_head != '')
and category in ('Total', 'Valuation and Total')
and parent in (%s)
""" % ', '.join(['%s']*len(invoice_item_row)), tuple(invoice_item_row.keys()))
@ -120,17 +143,17 @@ def get_tax_accounts(item_list, columns):
if item_wise_tax_detail:
try:
item_wise_tax_detail = json.loads(item_wise_tax_detail)
for item_code, tax_amount in item_wise_tax_detail.items():
tax_amount = flt(tax_amount[1]) if isinstance(tax_amount, list) else flt(tax_amount)
item_net_amount = sum([flt(d.base_net_amount)
item_net_amount = sum([flt(d.base_net_amount)
for d in item_row_map.get(parent, {}).get(item_code, [])])
for d in item_row_map.get(parent, {}).get(item_code, []):
item_tax_amount = flt((tax_amount * d.base_net_amount) / item_net_amount) if item_net_amount else 0
item_row_tax.setdefault(d.name, {})[account_head] = item_tax_amount
except ValueError:
continue
elif charge_type == "Actual" and tax_amount:

View File

@ -8,11 +8,14 @@ from frappe.utils import flt
from erpnext.accounts.report.sales_register.sales_register import get_mode_of_payments
def execute(filters=None):
return _execute(filters)
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
if not filters: filters = {}
columns = get_columns()
columns = get_columns(additional_table_columns)
last_col = len(columns)
item_list = get_items(filters)
item_list = get_items(filters, additional_query_columns)
if item_list:
item_row_tax, tax_accounts = get_tax_accounts(item_list, columns)
columns.append({
@ -35,10 +38,17 @@ def execute(filters=None):
if not delivery_note and d.update_stock:
delivery_note = d.parent
row = [d.item_code, d.item_name, d.item_group, d.parent, d.posting_date, d.customer, d.customer_name,
d.customer_group, d.debit_to, ", ".join(mode_of_payments.get(d.parent, [])),
row = [d.item_code, d.item_name, d.item_group, d.parent, d.posting_date, d.customer, d.customer_name]
if additional_query_columns:
for col in additional_query_columns:
row.append(d.get(col))
row += [
d.customer_group, d.debit_to, ", ".join(mode_of_payments.get(d.parent, [])),
d.territory, d.project, d.company, d.sales_order,
delivery_note, d.income_account, d.cost_center, d.qty, d.base_net_rate, d.base_net_amount]
delivery_note, d.income_account, d.cost_center, d.qty, d.base_net_rate, d.base_net_amount
]
for tax in tax_accounts:
row.append(item_row_tax.get(d.name, {}).get(tax, 0))
@ -50,12 +60,18 @@ def execute(filters=None):
return columns, data
def get_columns():
return [
def get_columns(additional_table_columns):
columns = [
_("Item Code") + ":Link/Item:120", _("Item Name") + "::120",
_("Item Group") + ":Link/Item Group:100", _("Invoice") + ":Link/Sales Invoice:120",
_("Posting Date") + ":Date:80", _("Customer") + ":Link/Customer:120",
_("Customer Name") + "::120", _("Customer Group") + ":Link/Customer Group:120",
_("Customer Name") + "::120"]
if additional_table_columns:
columns += additional_table_columns
columns += [
_("Customer Group") + ":Link/Customer Group:120",
_("Receivable Account") + ":Link/Account:120",
_("Mode of Payment") + "::120", _("Territory") + ":Link/Territory:80",
_("Project") + ":Link/Project:80", _("Company") + ":Link/Company:100",
@ -66,6 +82,8 @@ def get_columns():
_("Amount") + ":Currency/currency:120"
]
return columns
def get_conditions(filters):
conditions = ""
@ -76,15 +94,18 @@ def get_conditions(filters):
("to_date", " and si.posting_date<=%(to_date)s")):
if filters.get(opts[0]):
conditions += opts[1]
if filters.get("mode_of_payment"):
conditions += """ and exists(select name from `tabSales Invoice Payment`
where parent=si.name
where parent=si.name
and ifnull(`tabSales Invoice Payment`.mode_of_payment, '') = %(mode_of_payment)s)"""
return conditions
def get_items(filters):
def get_items(filters, additional_query_columns):
if additional_query_columns:
additional_query_columns = ', ' + ', '.join(additional_query_columns)
conditions = get_conditions(filters)
return frappe.db.sql("""
select
@ -93,10 +114,11 @@ def get_items(filters):
si_item.item_code, si_item.item_name, si_item.item_group, si_item.sales_order,
si_item.delivery_note, si_item.income_account, si_item.cost_center, si_item.qty,
si_item.base_net_rate, si_item.base_net_amount, si.customer_name,
si.customer_group, si_item.so_detail, si.update_stock
si.customer_group, si_item.so_detail, si.update_stock {0}
from `tabSales Invoice` si, `tabSales Invoice Item` si_item
where si.name = si_item.parent and si.docstatus = 1 %s
order by si.posting_date desc, si_item.item_code desc""" % conditions, filters, as_dict=1)
order by si.posting_date desc, si_item.item_code desc
""".format(additional_query_columns or '') % conditions, filters, as_dict=1)
def get_tax_accounts(item_list, columns):
import json

View File

@ -7,10 +7,13 @@ from frappe.utils import flt
from frappe import msgprint, _
def execute(filters=None):
return _execute(filters)
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
if not filters: filters = {}
invoice_list = get_invoices(filters)
columns, expense_accounts, tax_accounts = get_columns(invoice_list)
invoice_list = get_invoices(filters, additional_query_columns)
columns, expense_accounts, tax_accounts = get_columns(invoice_list, additional_table_columns)
if not invoice_list:
msgprint(_("No record found"))
@ -20,8 +23,9 @@ def execute(filters=None):
invoice_expense_map, invoice_tax_map = get_invoice_tax_map(invoice_list,
invoice_expense_map, expense_accounts)
invoice_po_pr_map = get_invoice_po_pr_map(invoice_list)
supplier_details = get_supplier_details(invoice_list)
suppliers = list(set([d.supplier for d in invoice_list]))
supplier_details = get_supplier_details(suppliers)
company_currency = frappe.db.get_value("Company", filters.company, "default_currency")
data = []
@ -31,10 +35,18 @@ def execute(filters=None):
purchase_receipt = list(set(invoice_po_pr_map.get(inv.name, {}).get("purchase_receipt", [])))
project = list(set(invoice_po_pr_map.get(inv.name, {}).get("project", [])))
row = [inv.name, inv.posting_date, inv.supplier, inv.supplier_name,
supplier_details.get(inv.supplier),
inv.credit_to, inv.mode_of_payment, ", ".join(project), inv.bill_no, inv.bill_date, inv.remarks,
", ".join(purchase_order), ", ".join(purchase_receipt), company_currency]
row = [inv.name, inv.posting_date, inv.supplier, inv.supplier_name]
if additional_query_columns:
for col in additional_query_columns:
row.append(inv.get(col))
row += [
supplier_details.get(inv.supplier), # supplier_type
inv.credit_to, inv.mode_of_payment, ", ".join(project),
inv.bill_no, inv.bill_date, inv.remarks,
", ".join(purchase_order), ", ".join(purchase_receipt), company_currency
]
# map expense values
base_net_total = 0
@ -61,15 +73,20 @@ def execute(filters=None):
return columns, data
def get_columns(invoice_list):
def get_columns(invoice_list, additional_table_columns):
"""return columns based on filters"""
columns = [
_("Invoice") + ":Link/Purchase Invoice:120", _("Posting Date") + ":Date:80",
_("Supplier Id") + "::120", _("Supplier Name") + "::120",
_("Supplier Type") + ":Link/Supplier Type:120", _("Payable Account") + ":Link/Account:120",
_("Mode of Payment") + ":Link/Mode of Payment:80", _("Project") + ":Link/Project:80",
_("Invoice") + ":Link/Purchase Invoice:120", _("Posting Date") + ":Date:80",
_("Supplier Id") + "::120", _("Supplier Name") + "::120"]
if additional_table_columns:
columns += additional_table_columns
columns += [
_("Supplier Type") + ":Link/Supplier Type:120", _("Payable Account") + ":Link/Account:120",
_("Mode of Payment") + ":Link/Mode of Payment:80", _("Project") + ":Link/Project:80",
_("Bill No") + "::120", _("Bill Date") + ":Date:80", _("Remarks") + "::150",
_("Purchase Order") + ":Link/Purchase Order:100",
_("Purchase Order") + ":Link/Purchase Order:100",
_("Purchase Receipt") + ":Link/Purchase Receipt:100",
{
"fieldname": "currency",
@ -114,27 +131,31 @@ def get_conditions(filters):
if filters.get("from_date"): conditions += " and posting_date>=%(from_date)s"
if filters.get("to_date"): conditions += " and posting_date<=%(to_date)s"
if filters.get("mode_of_payment"): conditions += " and ifnull(mode_of_payment, '') = %(mode_of_payment)s"
return conditions
def get_invoices(filters):
def get_invoices(filters, additional_query_columns):
if additional_query_columns:
additional_query_columns = ', ' + ', '.join(additional_query_columns)
conditions = get_conditions(filters)
return frappe.db.sql("""
select
name, posting_date, credit_to, supplier, supplier_name, bill_no, bill_date, remarks,
base_net_total, base_grand_total, outstanding_amount, mode_of_payment
from `tabPurchase Invoice`
select
name, posting_date, credit_to, supplier, supplier_name, bill_no, bill_date,
remarks, base_net_total, base_grand_total, outstanding_amount,
mode_of_payment {0}
from `tabPurchase Invoice`
where docstatus = 1 %s
order by posting_date desc, name desc""" % conditions, filters, as_dict=1)
order by posting_date desc, name desc""".format(additional_query_columns or '') % conditions, filters, as_dict=1)
def get_invoice_expense_map(invoice_list):
expense_details = frappe.db.sql("""
select parent, expense_account, sum(base_net_amount) as amount
from `tabPurchase Invoice Item`
where parent in (%s)
from `tabPurchase Invoice Item`
where parent in (%s)
group by parent, expense_account
""" % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
@ -149,7 +170,7 @@ def get_invoice_tax_map(invoice_list, invoice_expense_map, expense_accounts):
tax_details = frappe.db.sql("""
select parent, account_head, case add_deduct_tax when "Add" then sum(base_tax_amount_after_discount_amount)
else sum(base_tax_amount_after_discount_amount) * -1 end as tax_amount
from `tabPurchase Taxes and Charges`
from `tabPurchase Taxes and Charges`
where parent in (%s) and category in ('Total', 'Valuation and Total')
group by parent, account_head, add_deduct_tax
""" % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
@ -169,8 +190,8 @@ def get_invoice_tax_map(invoice_list, invoice_expense_map, expense_accounts):
def get_invoice_po_pr_map(invoice_list):
pi_items = frappe.db.sql("""
select parent, purchase_order, purchase_receipt, po_detail, project
from `tabPurchase Invoice Item`
select parent, purchase_order, purchase_receipt, po_detail, project
from `tabPurchase Invoice Item`
where parent in (%s) and (ifnull(purchase_order, '') != '' or ifnull(purchase_receipt, '') != '')
""" % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
@ -205,9 +226,8 @@ def get_account_details(invoice_list):
return account_map
def get_supplier_details(invoice_list):
def get_supplier_details(suppliers):
supplier_details = {}
suppliers = list(set([inv.supplier for inv in invoice_list]))
for supp in frappe.db.sql("""select name, supplier_type from `tabSupplier`
where name in (%s)""" % ", ".join(["%s"]*len(suppliers)), tuple(suppliers), as_dict=1):
supplier_details.setdefault(supp.name, supp.supplier_type)

View File

@ -7,10 +7,13 @@ from frappe.utils import flt
from frappe import msgprint, _
def execute(filters=None):
return _execute(filters)
def _execute(filters, additional_table_columns=None, additional_query_columns=None):
if not filters: filters = frappe._dict({})
invoice_list = get_invoices(filters)
columns, income_accounts, tax_accounts = get_columns(invoice_list)
invoice_list = get_invoices(filters, additional_query_columns)
columns, income_accounts, tax_accounts = get_columns(invoice_list, additional_table_columns)
if not invoice_list:
msgprint(_("No record found"))
@ -21,7 +24,8 @@ def execute(filters=None):
invoice_income_map, income_accounts)
invoice_so_dn_map = get_invoice_so_dn_map(invoice_list)
customer_map = get_customer_details(invoice_list)
customers = list(set([inv.customer for inv in invoice_list]))
customer_map = get_customer_details(customers)
company_currency = frappe.db.get_value("Company", filters.company, "default_currency")
mode_of_payments = get_mode_of_payments([inv.name for inv in invoice_list])
@ -31,12 +35,22 @@ def execute(filters=None):
sales_order = list(set(invoice_so_dn_map.get(inv.name, {}).get("sales_order", [])))
delivery_note = list(set(invoice_so_dn_map.get(inv.name, {}).get("delivery_note", [])))
row = [inv.name, inv.posting_date, inv.customer, inv.customer_name,
customer_map.get(inv.customer, {}).get("customer_group"),
customer_map.get(inv.customer, {}).get("territory"),
inv.debit_to, ", ".join(mode_of_payments.get(inv.name, [])), inv.project, inv.remarks,
", ".join(sales_order), ", ".join(delivery_note), company_currency]
customer_details = customer_map.get(inv.customer, {})
row = [
inv.name, inv.posting_date, inv.customer, inv.customer_name
]
if additional_query_columns:
for col in additional_query_columns:
row.append(inv.get(col))
row +=[
customer_details.get("customer_group"),
customer_details.get("territory"),
inv.debit_to, ", ".join(mode_of_payments.get(inv.name, [])),
inv.project, inv.remarks,
", ".join(sales_order), ", ".join(delivery_note), company_currency
]
# map income values
base_net_total = 0
for income_acc in income_accounts:
@ -62,15 +76,20 @@ def execute(filters=None):
return columns, data
def get_columns(invoice_list):
def get_columns(invoice_list, additional_table_columns):
"""return columns based on filters"""
columns = [
_("Invoice") + ":Link/Sales Invoice:120", _("Posting Date") + ":Date:80",
_("Customer Id") + "::120", _("Customer Name") + "::120",
_("Customer Group") + ":Link/Customer Group:120", _("Territory") + ":Link/Territory:80",
_("Receivable Account") + ":Link/Account:120", _("Mode of Payment") + "::120",
_("Project") +":Link/Project:80", _("Remarks") + "::150",
_("Invoice") + ":Link/Sales Invoice:120", _("Posting Date") + ":Date:80",
_("Customer") + ":Link/Customer:120", _("Customer Name") + "::120"
]
if additional_table_columns:
columns += additional_table_columns
columns +=[
_("Customer Group") + ":Link/Customer Group:120", _("Territory") + ":Link/Territory:80",
_("Receivable Account") + ":Link/Account:120", _("Mode of Payment") + "::120",
_("Project") +":Link/Project:80", _("Remarks") + "::150",
_("Sales Order") + ":Link/Sales Order:100", _("Delivery Note") + ":Link/Delivery Note:100",
{
"fieldname": "currency",
@ -113,20 +132,23 @@ def get_conditions(filters):
if filters.get("from_date"): conditions += " and posting_date >= %(from_date)s"
if filters.get("to_date"): conditions += " and posting_date <= %(to_date)s"
if filters.get("mode_of_payment"):
conditions += """ and exists(select name from `tabSales Invoice Payment`
where parent=`tabSales Invoice`.name
where parent=`tabSales Invoice`.name
and ifnull(`tabSales Invoice Payment`.mode_of_payment, '') = %(mode_of_payment)s)"""
return conditions
def get_invoices(filters):
def get_invoices(filters, additional_query_columns):
if additional_query_columns:
additional_query_columns = ', ' + ', '.join(additional_query_columns)
conditions = get_conditions(filters)
return frappe.db.sql("""select name, posting_date, debit_to, project, customer, customer_name, remarks,
base_net_total, base_grand_total, base_rounded_total, outstanding_amount
return frappe.db.sql("""select name, posting_date, debit_to, project, customer, customer_name, remarks,
base_net_total, base_grand_total, base_rounded_total, outstanding_amount {0}
from `tabSales Invoice`
where docstatus = 1 %s order by posting_date desc, name desc""" %
where docstatus = 1 %s order by posting_date desc, name desc""".format(additional_query_columns or '') %
conditions, filters, as_dict=1)
def get_invoice_income_map(invoice_list):
@ -184,9 +206,8 @@ def get_invoice_so_dn_map(invoice_list):
return invoice_so_dn_map
def get_customer_details(invoice_list):
def get_customer_details(customers):
customer_map = {}
customers = list(set([inv.customer for inv in invoice_list]))
for cust in frappe.db.sql("""select name, territory, customer_group from `tabCustomer`
where name in (%s)""" % ", ".join(["%s"]*len(customers)), tuple(customers), as_dict=1):
customer_map.setdefault(cust.name, cust)

View File

@ -35,7 +35,7 @@ def get_data():
{
"type": "report",
"name": "Accounts Receivable",
"doctype": "Sales Invoice",
"doctype": "Sales Invoice",
"is_query_report": True
},
{
@ -198,6 +198,35 @@ def get_data():
},
]
},
{
"label": _("Goods and Services Tax (GST India)"),
"items": [
{
"type": "doctype",
"name": "GST HSN Code",
},
{
"type": "report",
"name": "GST Sales Register",
"is_query_report": True
},
{
"type": "report",
"name": "GST Purchase Register",
"is_query_report": True
},
{
"type": "report",
"name": "GST Itemised Sales Register",
"is_query_report": True
},
{
"type": "report",
"name": "GST Itemised Purchase Register",
"is_query_report": True
},
]
},
{
"label": _("Budget and Cost Center"),
"items": [

View File

@ -316,6 +316,8 @@ def setup_account():
doc.parent_account = frappe.db.get_value('Account', {'account_name': doc.parent_account})
doc.insert()
frappe.flags.in_import = False
def setup_account_to_expense_type():
company_abbr = frappe.db.get_value("Company", erpnext.get_default_company(), "abbr")
expense_types = [{'name': _('Calls'), "account": "Sales Expenses - "+ company_abbr},
@ -380,4 +382,6 @@ def import_json(doctype, submit=False, values=None):
frappe.db.commit()
frappe.flags.in_import = False

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 789 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 KiB

View File

@ -12,4 +12,5 @@ human-resources
customer-portal
website
using-erpnext
regional
customize-erpnext

View File

@ -0,0 +1,9 @@
ERPNext aims to support local regulation for all the regions in the world. In most cases ERPNext is very flexible so you can easily add Custom Fields and make Custom Reports to support the regluation of your region.
As of mid-2017, ERPNext aims to pre-set additional fields and forms required for companies to easily submit reports to the relevant authorities.
This section is still under-development.
### Regions
{index}

View File

@ -0,0 +1,71 @@
# Statutory Requirements for India
As of 2017, India will fall under the new GST (Goods and Services Tax) regime and ERPNext makes it easy for users to track the details of its Supplier and Customers across Invoices and make the required reports.
## GST Features in ERPNext
### 1. Setting up GSTIN
GST Law requires that you maintain the GSTIN number for all your suppliers and vendors. In ERPNext, GSTIN is linked to the **Address**
<img class="screenshot" alt="GST in Customer" src="{{docs_base_url}}/assets/img/regional/india/gstin-customer.gif">
**GST for your Company Address**
You also need to set the Address for your own Company and your Company's GST Number
Go to the Company master and add the GSTIN to your default address.
<img class="screenshot" alt="GST in Company" src="{{docs_base_url}}/assets/img/regional/india/gstin-company.gif">
### 2. Setting up HSN Codes
According to the GST Law, your itemised invoices must contain the HSN Code related to that Item. ERPNext comes pre-installed with all 12,000+ HSN Codes so that you can easily select the relevant HSN Code in your Item
<img class="screenshot" alt="HSN in Item" src="{{docs_base_url}}/assets/img/regional/india/hsn-item.gif">
### 3. Making Tax Masters
To setup Billing in GST, you need to create 3 Tax Accounts for the various GST reporting heads CGST - Central GST, SGST - State GST, IGST - Inter-state GST
Go to your **Chart of Accounts**, under the Duties and Taxes head of your account, create 3 Accounts
**Note:** Usually the rate in CGST and SGST is half of IGST. For example if most of your items are billed at 18%, then create IGST at 18%, CGST and SGST at 9% each.
<img class="screenshot" alt="GST in Customer" src="{{docs_base_url}}/assets/img/regional/india/gst-in-coa.png">
### 4. Make Tax Templates
You will have have to make two tax templates for both your sales and purchase, one for in state sales and other for out of state sales.
In your **In State GST** template, select 2 accounts, SGST and CGST
<img class="screenshot" alt="GST in Customer" src="{{docs_base_url}}/assets/img/regional/india/gst-template-in-state.png">
In your **Out of State GST** template, select IGST
### 5. Making GST Ready Invoices
If you have setup the GSTIN of your Customers and Suppliers, and your tax template, you are ready to go for making GST Ready Invoices!
For **Sales Invoice**,
1. Select the correct Customer and Item and the address where the transaction will happen.
2. Check if the GSTIN of your Company and Supplier have been correctly set.
3. Check if the HSN Number has been set in the Item
4. Select the the **In State GST** or **Out of State GST** template that you have created based on the type of transaction
5. Save and Submit the Invoice
<img class="screenshot" alt="GST Invoice" src="{{docs_base_url}}/assets/img/regional/india/gst-invoice.gif">
### Reports
ERPNext comes with most of your reports you need to prepare your GST Returns. Go to Accounts > GST India head for the list.
<img class="screenshot" alt="GST Menus" src="{{docs_base_url}}/assets/img/regional/india/gst-menu.png">
You can check the impact of your invoice in the **GST Sales Register** and **GST Itemised Sales Register**
<img class="screenshot" alt="GST Itemised Sales Register" src="{{docs_base_url}}/assets/img/regional/india/gst-itemised.png">

View File

@ -160,6 +160,9 @@ doc_events = {
},
"Payment Entry": {
"on_submit": "erpnext.accounts.doctype.payment_request.payment_request.make_status_as_paid"
},
'Address': {
'validate': 'erpnext.regional.india.utils.validate_gstin_for_india'
}
}

View File

@ -13,4 +13,5 @@ Shopping Cart
Hub Node
Portal
Maintenance
Schools
Schools
Regional

View File

@ -406,4 +406,5 @@ erpnext.patches.v8_0.change_in_words_varchar_length
erpnext.patches.v8_0.create_domain_docs #16-05-2017
erpnext.patches.v8_0.update_sales_cost_in_project
erpnext.patches.v8_0.save_system_settings
erpnext.patches.v8_1.delete_deprecated_reports
erpnext.patches.v8_1.delete_deprecated_reports
erpnext.patches.v8_1.setup_gst_india

View File

@ -0,0 +1,13 @@
import frappe
def execute():
frappe.reload_doc('regional', 'doctype', 'gst_hsn_code')
for report_name in ('GST Sales Register', 'GST Purchase Register',
'GST Itemised Sales Register', 'GST Itemised Purchase Register'):
frappe.reload_doc('regional', 'report', frappe.scrub(report_name))
if frappe.db.get_single_value('System Settings', 'country')=='India':
from erpnext.regional.india.setup import setup
setup()

View File

@ -104,7 +104,7 @@ body[data-route="pos"] .pos-payment-row {
}
body[data-route="pos"] .pos-payment-row:hover,
body[data-route="pos"] .pos-keyboard-key:hover {
background-color: #FAFBFC;
background-color: #fafbfc;
cursor: pointer;
}
body[data-route="pos"] .pos-keyboard-key,
@ -214,7 +214,7 @@ body[data-route="pos"] .amount-label {
font-size: 16px;
}
body[data-route="pos"] .selected-payment-mode {
background-color: #FAFBFC;
background-color: #fafbfc;
cursor: pointer;
}
body[data-route="pos"] .pos-invoice-list {

View File

@ -51,20 +51,28 @@ $.extend(erpnext.queries, {
return {
query: 'frappe.contacts.doctype.contact.contact.contact_query',
filters: { link_doctype: frappe.dynamic_link.doctype, link_name: doc[frappe.dynamic_link.fieldname] } };
filters: {
link_doctype: frappe.dynamic_link.doctype,
link_name: doc[frappe.dynamic_link.fieldname]
}
};
}
},
address_query: function(doc) {
if(frappe.dynamic_link) {
if(!doc[frappe.dynamic_link.fieldname]) {
frappe.throw(__("Please set {0}",
frappe.throw(__("Please set {0}",
[__(frappe.meta.get_label(doc.doctype, frappe.dynamic_link.fieldname, doc.name))]));
}
return {
query: 'frappe.contacts.doctype.address.address.address_query',
filters: { link_doctype: frappe.dynamic_link.doctype, link_name: doc[frappe.dynamic_link.fieldname] } };
filters: {
link_doctype: frappe.dynamic_link.doctype,
link_name: doc[frappe.dynamic_link.fieldname]
}
};
}
},
@ -85,7 +93,7 @@ $.extend(erpnext.queries, {
lead_filter: function(doc) {
if(!doc.lead) {
frappe.throw(__("Please specify a {0}",
frappe.throw(__("Please specify a {0}",
[__(frappe.meta.get_label(doc.doctype, "lead", doc.name))]));
}

View File

@ -1,6 +1,6 @@
<p><button class="btn btn-xs btn-default btn-address">{{ __("New Address") }}</button></p>
<div class="clearfix"></div>
{% for(var i=0, l=addr_list.length; i<l; i++) { %}
<div class="address-box">
<p class="h6">
{%= i+1 %}. {%= addr_list[i].address_type!="Other" ? __(addr_list[i].address_type) : addr_list[i].address_title %}
{% if(addr_list[i].is_primary_address) { %}
@ -9,14 +9,15 @@
<span class="text-muted">({%= __("Shipping") %})</span>{% } %}
<a href="#Form/Address/{%= encodeURIComponent(addr_list[i].name) %}"
class="btn btn-default btn-xs pull-right">
class="btn btn-default btn-xs pull-right"
style="margin-top:-3px; margin-right: -5px;">
{%= __("Edit") %}</a>
</p>
<div style="padding-left: 15px;">
<p style="margin-top: 5px; font-size: 12px;">
{%= addr_list[i].display %}</p>
</p>
<p>{%= addr_list[i].display %}</p>
</div>
{% } %}
{% if(!addr_list.length) { %}
<p class="text-muted">{%= __("No address added yet.") %}</p>
<p class="text-muted small">{%= __("No address added yet.") %}</p>
{% } %}
<p><button class="btn btn-xs btn-default btn-address">{{ __("New Address") }}</button></p>

View File

@ -1,38 +1,38 @@
<p><button class="btn btn-xs btn-default btn-contact">
{{ __("New Contact") }}</button></p>
<div class="clearfix"></div>
<ol>
<div class="clearfix"></div>
{% for(var i=0, l=contact_list.length; i<l; i++) { %}
<p class="h6">
<li>
{%= contact_list[i].first_name %} {%= contact_list[i].last_name %}
{% if(contact_list[i].is_primary_contact) { %}
<span class="text-muted">({%= __("Primary") %})</span>
{% } %}
{% if(contact_list[i].designation){ %}
<span class="text-muted">&ndash; {%= contact_list[i].designation %}</span>
{% } %}
<a href="#Form/Contact/{%= encodeURIComponent(contact_list[i].name) %}"
class="btn btn-xs btn-default pull-right">
{%= __("Edit") %}</a>
</li>
</p>
<div style="padding-left: 15px;">
<p style="padding-top: 5px; font-size: 12px;">
{% if(contact_list[i].phone) { %}
{%= __("Phone") %}: {%= contact_list[i].phone %}<br>
{% } %}
{% if(contact_list[i].mobile_no) { %}
{%= __("Mobile No.") %}: {%= contact_list[i].mobile_no %}<br>
{% } %}
{% if(contact_list[i].email_id) { %}
{%= __("Email Address") %}: {%= contact_list[i].email_id %}
{% } %}
</p>
</div>
<div class="address-box">
<p class="h6">
{%= contact_list[i].first_name %} {%= contact_list[i].last_name %}
{% if(contact_list[i].is_primary_contact) { %}
<span class="text-muted">({%= __("Primary") %})</span>
{% } %}
{% if(contact_list[i].designation){ %}
<span class="text-muted">&ndash; {%= contact_list[i].designation %}</span>
{% } %}
<a href="#Form/Contact/{%= encodeURIComponent(contact_list[i].name) %}"
class="btn btn-xs btn-default pull-right"
style="margin-top:-3px; margin-right: -5px;">
{%= __("Edit") %}</a>
</p>
{% if (contact_list[i].phone || contact_list[i].mobile_no ||
contact_list[i].email_id) { %}
<p>
{% if(contact_list[i].phone) { %}
{%= __("Phone") %}: {%= contact_list[i].phone %}<br>
{% } %}
{% if(contact_list[i].mobile_no) { %}
{%= __("Mobile No.") %}: {%= contact_list[i].mobile_no %}<br>
{% } %}
{% if(contact_list[i].email_id) { %}
{%= __("Email Address") %}: {%= contact_list[i].email_id %}
{% } %}
</p>
{% endif %}
</div>
{% } %}
</ol>
{% if(!contact_list.length) { %}
<p class="text-muted">{%= __("No contacts added yet.") %}</p>
{% } %}
<p class="text-muted small">{%= __("No contacts added yet.") %}</p>
{% } %}
<p><button class="btn btn-xs btn-default btn-contact">
{{ __("New Contact") }}</button>
</p>

View File

@ -126,7 +126,7 @@ body[data-route="pos"] {
}
.pos-payment-row {
border-bottom:1px solid #d1d8dd;
border-bottom:1px solid @border-color;
margin: 2px 0px 5px 0px;
height: 60px;
margin-top: 0px;
@ -134,12 +134,12 @@ body[data-route="pos"] {
}
.pos-payment-row:hover, .pos-keyboard-key:hover{
background-color: #FAFBFC;
background-color: @light-bg;
cursor: pointer;
}
.pos-keyboard-key, .delete-btn {
border: 1px solid #d1d8dd;
border: 1px solid @border-color;
height:85px;
width:85px;
margin:10px 10px;
@ -150,7 +150,7 @@ body[data-route="pos"] {
}
.numeric-keypad {
border: 1px solid #d1d8dd;
border: 1px solid @border-color;
height:69px;
width:69px;
font-size:20px;
@ -256,7 +256,7 @@ body[data-route="pos"] {
}
.selected-payment-mode {
background-color: #FAFBFC;
background-color: @light-bg;
cursor: pointer;
}
@ -355,7 +355,7 @@ body[data-route="pos"] {
.image-field {
height: 140px;
.placeholder-text {
font-size: 50px;
}

View File

View File

View File

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

View File

@ -0,0 +1,103 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "fieldname:hsn_code",
"beta": 0,
"creation": "2017-06-21 10:48:56.422086",
"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": "hsn_code",
"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,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "description",
"fieldtype": "Small Text",
"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": "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,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-06-21 13:27:59.149202",
"modified_by": "Administrator",
"module": "Regional",
"name": "GST HSN Code",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"search_fields": "description",
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
}

View File

@ -0,0 +1,10 @@
# -*- 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
from frappe.model.document import Document
class GSTHSNCode(Document):
pass

View File

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

View File

@ -0,0 +1,76 @@
states = [
'',
'Andhra Pradesh',
'Arunachal Pradesh',
'Assam',
'Bihar',
'Chandigarh',
'Chattisgarh',
'Dadra and Nagar Haveli',
'Daman and Diu',
'Delhi',
'Goa',
'Gujarat',
'Haryana',
'Himachal Pradesh',
'Jammu and Kashmir',
'Jharkhand',
'Karnataka',
'Kerala',
'Lakshadweep Islands',
'Madhya Pradesh',
'Maharashtra',
'Manipur',
'Meghalaya',
'Mizoram',
'Nagaland',
'Odisha',
'Pondicherry',
'Punjab',
'Rajasthan',
'Sikkim',
'Tamil Nadu',
'Telangana',
'Tripura',
'Uttar Pradesh',
'Uttarakhand',
'West Bengal',
]
state_numbers = {
"Andhra Pradesh": "37",
"Arunachal Pradesh": "12",
"Assam": "18",
"Bihar": "10",
"Chandigarh": "04",
"Chattisgarh": "22",
"Dadra and Nagar Haveli": "26",
"Daman and Diu": "25",
"Delhi": "07",
"Goa": "30",
"Gujarat": "24",
"Haryana": "06",
"Himachal Pradesh": "02",
"Jammu and Kashmir": "01",
"Jharkhand": "20",
"Karnataka": "29",
"Kerala": "32",
"Lakshadweep Islands": "31",
"Madhya Pradesh": "23",
"Maharashtra": "27",
"Manipur": "14",
"Meghalaya": "17",
"Mizoram": "15",
"Nagaland": "13",
"Odisha": "21",
"Pondicherry": "34",
"Punjab": "03",
"Rajasthan": "08",
"Sikkim": "11",
"Tamil Nadu": "33",
"Telangana": "36",
"Tripura": "16",
"Uttar Pradesh": "35",
"Uttarakhand": "36",
"West Bengal": "37"
}

View File

@ -0,0 +1,8 @@
{{ address_line1 }}<br>{% if address_line2 %}{{ address_line2 }}<br>{% endif -%}{{ city }}<br>
{% if state %}{{ state }}<br>{% endif -%}
{% if pincode %}{{ pincode }}<br>{% endif -%}
{{ country }}<br>
{% if gstin %}GSTIN: {{ gstin }}<br>{% endif -%}
{% if phone %}Phone: {{ phone }}<br>{% endif -%}
{% if fax %}Fax: {{ fax }}<br>{% endif -%}
{% if email_id %}Email: {{ email_id }}<br>{% endif -%}

View File

@ -0,0 +1,177 @@
[
{
"state_number": "33",
"state_code": "TN",
"state_name": "Tamil Nadu"
},
{
"state_number": "35",
"state_code": "UP",
"state_name": "Uttar Pradesh"
},
{
"state_number": "36",
"state_code": "UT",
"state_name": "Uttarakhand"
},
{
"state_number": "37",
"state_code": "WB",
"state_name": "West Bengal"
},
{
"state_number": "16",
"state_code": "TR",
"state_name": "Tripura"
},
{
"state_number": "36",
"state_code": "TS",
"state_name": "Telangana"
},
{
"state_number": "11",
"state_code": "SK",
"state_name": "Sikkim"
},
{
"state_number": "08",
"state_code": "RJ",
"state_name": "Rajasthan"
},
{
"state_number": "03",
"state_code": "PB",
"state_name": "Punjab"
},
{
"state_number": "34",
"state_code": "PY",
"state_name": "Pondicherry"
},
{
"state_number": "21",
"state_code": "OR",
"state_name": "Odisha"
},
{
"state_number": "13",
"state_code": "NL",
"state_name": "Nagaland"
},
{
"state_number": "15",
"state_code": "MI",
"state_name": "Mizoram"
},
{
"state_number": "17",
"state_code": "ME",
"state_name": "Meghalaya"
},
{
"state_number": "14",
"state_code": "MN",
"state_name": "Manipur"
},
{
"state_number": "27",
"state_code": "MH",
"state_name": "Maharashtra"
},
{
"state_number": "23",
"state_code": "MP",
"state_name": "Madhya Pradesh"
},
{
"state_number": "31",
"state_code": "LD",
"state_name": "Lakshadweep Islands"
},
{
"state_number": "32",
"state_code": "KL",
"state_name": "Kerala"
},
{
"state_number": "29",
"state_code": "KA",
"state_name": "Karnataka"
},
{
"state_number": "20",
"state_code": "JH",
"state_name": "Jharkhand"
},
{
"state_number": "01",
"state_code": "JK",
"state_name": "Jammu and Kashmir"
},
{
"state_number": "02",
"state_code": "HP",
"state_name": "Himachal Pradesh"
},
{
"state_number": "06",
"state_code": "HR",
"state_name": "Haryana"
},
{
"state_number": "24",
"state_code": "GJ",
"state_name": "Gujarat"
},
{
"state_number": "30",
"state_code": "GA",
"state_name": "Goa"
},
{
"state_number": "07",
"state_code": "DL",
"state_name": "Delhi"
},
{
"state_number": "25",
"state_code": "DD",
"state_name": "Daman and Diu"
},
{
"state_number": "26",
"state_code": "DN",
"state_name": "Dadra and Nagar Haveli"
},
{
"state_number": "22",
"state_code": "CT",
"state_name": "Chattisgarh"
},
{
"state_number": "04",
"state_code": "CH",
"state_name": "Chandigarh"
},
{
"state_number": "10",
"state_code": "BH",
"state_name": "Bihar"
},
{
"state_number": "18",
"state_code": "AS",
"state_name": "Assam"
},
{
"state_number": "12",
"state_code": "AR",
"state_name": "Arunachal Pradesh"
},
{
"state_number": "37",
"state_code": "AD",
"state_name": "Andhra Pradesh (New)"
}
]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,131 @@
# 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, os, json
from frappe.custom.doctype.custom_field.custom_field import create_custom_field
from frappe.permissions import add_permission
from erpnext.regional.india import states
def setup(company=None):
make_custom_fields()
make_fixtures()
add_permissions()
add_custom_roles_for_reports()
add_hsn_codes()
update_address_template()
def update_address_template():
with open(os.path.join(os.path.dirname(__file__), 'address_template.html'), 'r') as f:
html = f.read()
address_template = frappe.db.get_value('Address Template', 'India')
if address_template:
frappe.db.set_value('Address Template', 'India', 'template', html)
else:
# make new html template for India
frappe.get_doc(
doctype='Address Template',
country='India',
template=html
).insert()
def add_hsn_codes():
if frappe.db.count('GST HSN Code') > 100:
return
with open(os.path.join(os.path.dirname(__file__), 'hsn_code_data.json'), 'r') as f:
hsn_codes = json.loads(f.read())
frappe.db.commit()
frappe.db.sql('truncate `tabGST HSN Code`')
for d in hsn_codes:
hsn_code = frappe.new_doc('GST HSN Code')
hsn_code.update(d)
hsn_code.name = hsn_code.hsn_code
hsn_code.db_insert()
frappe.db.commit()
def add_custom_roles_for_reports():
for report_name in ('GST Sales Register', 'GST Purchase Register',
'GST Itemised Sales Register', 'GST Itemised Purchase Register'):
if not frappe.db.get_value('Custom Role', dict(report=report_name)):
frappe.get_doc(dict(
doctype='Custom Role',
report=report_name,
roles= [
dict(role='Accounts User'),
dict(role='Accounts Manager')
]
)).insert()
def add_permissions():
for doctype in ('GST HSN Code',):
add_permission(doctype, 'Accounts Manager', 0)
add_permission(doctype, 'All', 0)
def make_custom_fields():
custom_fields = {
'Address': [
dict(fieldname='gstin', label='Party GSTIN', fieldtype='Data',
insert_after='fax'),
dict(fieldname='gst_state', label='GST State', fieldtype='Select',
options='\n'.join(states), insert_after='gstin')
],
'Purchase Invoice': [
dict(fieldname='supplier_gstin', label='Supplier GSTIN',
fieldtype='Data', insert_after='supplier_address',
options='supplier_address.gstin'),
dict(fieldname='company_gstin', label='Company GSTIN',
fieldtype='Data', insert_after='shipping_address',
options='shipping_address.gstin'),
],
'Sales Invoice': [
dict(fieldname='customer_gstin', label='Customer GSTIN',
fieldtype='Data', insert_after='shipping_address',
options='shipping_address_name.gstin'),
dict(fieldname='company_gstin', label='Company GSTIN',
fieldtype='Data', insert_after='company_address',
options='company_address.gstin'),
],
'Item': [
dict(fieldname='gst_hsn_code', label='GST HSN Code',
fieldtype='Link', options='GST HSN Code', insert_after='item_group'),
],
'Sales Invoice Item': [
dict(fieldname='gst_hsn_code', label='GST HSN Code',
fieldtype='Data', options='item_code.gst_hsn_code',
insert_after='income_account'),
],
'Purchase Invoice Item': [
dict(fieldname='gst_hsn_code', label='GST HSN Code',
fieldtype='Data', options='item_code.gst_hsn_code',
insert_after='expense_account'),
]
}
for doctype, fields in custom_fields.items():
for df in fields:
create_custom_field(doctype, df)
def make_fixtures():
docs = [
{'doctype': 'Salary Component', 'salary_component': 'Professional Tax', 'description': 'Professional Tax', 'type': 'Deduction'},
{'doctype': 'Salary Component', 'salary_component': 'Provident Fund', 'description': 'Provident fund', 'type': 'Deduction'},
{'doctype': 'Salary Component', 'salary_component': 'House Rent Allowance', 'description': 'House Rent Allowance', 'type': 'Earning'},
{'doctype': 'Salary Component', 'salary_component': 'Basic', 'description': 'Basic', 'type': 'Earning'},
{'doctype': 'Salary Component', 'salary_component': 'Arrear', 'description': 'Arrear', 'type': 'Earning'},
{'doctype': 'Salary Component', 'salary_component': 'Leave Encashment', 'description': 'Leave Encashment', 'type': 'Earning'}
]
for d in docs:
try:
doc = frappe.get_doc(d)
doc.flags.ignore_permissions = True
doc.insert()
except frappe.NameError:
pass

View File

@ -0,0 +1,21 @@
import frappe, re
from frappe import _
from erpnext.regional.india import states, state_numbers
def validate_gstin_for_india(doc, method):
if not hasattr(doc, 'gstin'):
return
if doc.gstin:
p = re.compile("[0-9]{2}[a-zA-Z]{5}[0-9]{4}[a-zA-Z]{1}[1-9A-Za-z]{1}[Z]{1}[0-9a-zA-Z]{1}")
if not p.match(doc.gstin):
frappe.throw(_("Invalid GSTIN"))
if not doc.gst_state:
if doc.state in states:
doc.gst_state = doc.state
if doc.gst_state:
state_number = state_numbers[doc.gst_state]
if state_number != doc.gstin[:2]:
frappe.throw(_("First 2 digits of GSTIN should match with State number {0}").format(state_number))

View File

View File

@ -0,0 +1,7 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
/* eslint-disable */
{% include "erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.js" %}
frappe.query_reports["GST Itemised Purchase Register"] = frappe.query_reports["Item-wise Purchase Register"]

View File

@ -0,0 +1,19 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2017-06-22 15:25:04.101930",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2017-06-22 15:25:10.749203",
"modified_by": "Administrator",
"module": "Regional",
"name": "GST Itemised Purchase Register",
"owner": "Administrator",
"ref_doctype": "Purchase Invoice",
"report_name": "GST Itemised Purchase Register",
"report_type": "Script Report",
"roles": []
}

View File

@ -0,0 +1,17 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
from erpnext.accounts.report.item_wise_purchase_register.item_wise_purchase_register import _execute
def execute(filters=None):
return _execute(filters, additional_table_columns=[
dict(fieldtype='Data', label='Supplier GSTIN', width=120),
dict(fieldtype='Data', label='Company GSTIN', width=120),
dict(fieldtype='Data', label='HSN Code', width=120)
], additional_query_columns=[
'supplier_gstin',
'company_gstin',
'gst_hsn_code'
])

View File

@ -0,0 +1,7 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
/* eslint-disable */
{% include "erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js" %}
frappe.query_reports["GST Itemised Sales Register"] = frappe.query_reports["Item-wise Sales Register"]

View File

@ -0,0 +1,19 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2017-06-22 15:24:43.083217",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2017-06-22 15:24:50.611910",
"modified_by": "Administrator",
"module": "Regional",
"name": "GST Itemised Sales Register",
"owner": "Administrator",
"ref_doctype": "Sales Invoice",
"report_name": "GST Itemised Sales Register",
"report_type": "Script Report",
"roles": []
}

View File

@ -0,0 +1,17 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
from erpnext.accounts.report.item_wise_sales_register.item_wise_sales_register import _execute
def execute(filters=None):
return _execute(filters, additional_table_columns=[
dict(fieldtype='Data', label='Customer GSTIN', width=120),
dict(fieldtype='Data', label='Company GSTIN', width=120),
dict(fieldtype='Data', label='HSN Code', width=120)
], additional_query_columns=[
'customer_gstin',
'company_gstin',
'gst_hsn_code'
])

View File

@ -0,0 +1,7 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
/* eslint-disable */
{% include "erpnext/accounts/report/purchase_register/purchase_register.js" %}
frappe.query_reports["GST Purchase Register"] = frappe.query_reports["Purchase Register"]

View File

@ -0,0 +1,19 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2017-06-22 11:06:40.836073",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2017-06-22 12:17:15.487392",
"modified_by": "Administrator",
"module": "Regional",
"name": "GST Purchase Register",
"owner": "Administrator",
"ref_doctype": "Purchase Invoice",
"report_name": "GST Purchase Register",
"report_type": "Script Report",
"roles": []
}

View File

@ -0,0 +1,16 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
from erpnext.accounts.report.purchase_register.purchase_register import _execute
def execute(filters=None):
return _execute(filters, additional_table_columns=[
dict(fieldtype='Data', label='Supplier GSTIN', width=120),
dict(fieldtype='Data', label='Company GSTIN', width=120)
], additional_query_columns=[
'supplier_gstin',
'company_gstin'
])

View File

@ -0,0 +1,7 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
/* eslint-disable */
{% include "erpnext/accounts/report/sales_register/sales_register.js" %}
frappe.query_reports["GST Sales Register"] = frappe.query_reports["Sales Register"]

View File

@ -0,0 +1,19 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2017-06-21 16:44:41.621260",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2017-06-22 11:39:24.609998",
"modified_by": "Administrator",
"module": "Regional",
"name": "GST Sales Register",
"owner": "Administrator",
"ref_doctype": "Sales Invoice",
"report_name": "GST Sales Register",
"report_type": "Script Report",
"roles": []
}

View File

@ -0,0 +1,15 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
from erpnext.accounts.report.sales_register.sales_register import _execute
def execute(filters=None):
return _execute(filters, additional_table_columns=[
dict(fieldtype='Data', label='Customer GSTIN', width=120),
dict(fieldtype='Data', label='Company GSTIN', width=120)
], additional_query_columns=[
'customer_gstin',
'company_gstin'
])

View File

@ -20,8 +20,6 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
},
setup_queries: function() {
var me = this;
this.frm.add_fetch("sales_partner", "commission_rate", "commission_rate");

View File

@ -17,6 +17,8 @@ frappe.ui.form.on("Company", {
if(!frm.doc.__islocal) {
frappe.contacts.render_address_and_contact(frm);
frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Company'}
frm.toggle_enable("default_currency", (frm.doc.__onload &&
!frm.doc.__onload.transactions_exist));
@ -34,7 +36,7 @@ frappe.ui.form.on("Company", {
},
onload_post_render: function(frm) {
if(frm.get_field("delete_company_transactions").$input)
if(frm.get_field("delete_company_transactions").$input)
frm.get_field("delete_company_transactions").$input.addClass("btn-danger");
},
country: function(frm) {
@ -144,7 +146,7 @@ erpnext.company.setup_queries = function(frm) {
["round_off_account", {"root_type": "Expense"}],
["write_off_account", {"root_type": "Expense"}],
["exchange_gain_loss_account", {"root_type": "Expense"}],
["accumulated_depreciation_account",
["accumulated_depreciation_account",
{"root_type": "Asset", "account_type": "Accumulated Depreciation"}],
["depreciation_expense_account", {"root_type": "Expense", "account_type": "Depreciation"}],
["disposal_account", {"report_type": "Profit and Loss"}],
@ -158,11 +160,11 @@ erpnext.company.setup_queries = function(frm) {
if (frm.doc.enable_perpetual_inventory) {
$.each([
["stock_adjustment_account",
["stock_adjustment_account",
{"root_type": "Expense", "account_type": "Stock Adjustment"}],
["expenses_included_in_valuation",
["expenses_included_in_valuation",
{"root_type": "Expense", "account_type": "Expenses Included in Valuation"}],
["stock_received_but_not_billed",
["stock_received_but_not_billed",
{"root_type": "Liability", "account_type": "Stock Received But Not Billed"}]
], function(i, v) {
erpnext.company.set_custom_query(frm, v);

View File

@ -51,10 +51,10 @@ class Company(Document):
frappe.throw(_("Abbreviation already used for another company"))
def validate_default_accounts(self):
for field in ["default_bank_account", "default_cash_account",
"default_receivable_account", "default_payable_account",
"default_expense_account", "default_income_account",
"stock_received_but_not_billed", "stock_adjustment_account",
for field in ["default_bank_account", "default_cash_account",
"default_receivable_account", "default_payable_account",
"default_expense_account", "default_income_account",
"stock_received_but_not_billed", "stock_adjustment_account",
"expenses_included_in_valuation", "default_payroll_payable_account"]:
if self.get(field):
for_company = frappe.db.get_value("Account", self.get(field), "company")
@ -96,9 +96,9 @@ class Company(Document):
frappe.clear_cache()
def install_country_fixtures(self):
path = os.path.join(os.path.dirname(__file__), "fixtures", self.country.lower())
path = frappe.get_app_path('erpnext', 'regional', frappe.scrub(self.country))
if os.path.exists(path.encode("utf-8")):
frappe.get_attr("erpnext.setup.doctype.company.fixtures.{0}.install"
frappe.get_attr("erpnext.regional.{0}.setup.setup"
.format(self.country.lower()))(self)
def create_default_warehouses(self):

View File

@ -1,24 +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
def install(company):
docs = [
{'doctype': 'Salary Component', 'salary_component': 'Professional Tax', 'description': 'Professional Tax', 'type': 'Deduction'},
{'doctype': 'Salary Component', 'salary_component': 'Provident Fund', 'description': 'Provident fund', 'type': 'Deduction'},
{'doctype': 'Salary Component', 'salary_component': 'House Rent Allowance', 'description': 'House Rent Allowance', 'type': 'Earning'},
{'doctype': 'Salary Component', 'salary_component': 'Basic', 'description': 'Basic', 'type': 'Earning'},
{'doctype': 'Salary Component', 'salary_component': 'Arrear', 'description': 'Arrear', 'type': 'Earning'},
{'doctype': 'Salary Component', 'salary_component': 'Leave Encashment', 'description': 'Leave Encashment', 'type': 'Earning'}
]
for d in docs:
try:
doc = frappe.get_doc(d)
doc.flags.ignore_permissions = True
doc.insert()
except frappe.NameError:
pass

View File

@ -584,16 +584,24 @@
},
"India": {
"India VAT 5%": {
"account_name": "VAT 5%",
"tax_rate": 5.00,
"In State GST": {
"account_name": ["SGST", "CGST"],
"tax_rate": [9.00, 9.00],
"default": 1
},
"India VAT 4%": {
"Out of State GST": {
"account_name": "IGST",
"tax_rate": 18.00
},
"VAT 5%": {
"account_name": "VAT 5%",
"tax_rate": 5.00
},
"VAT 4%": {
"account_name": "VAT 4%",
"tax_rate": 4.00
},
"India VAT 14%": {
"VAT 14%": {
"account_name": "VAT 14%",
"tax_rate": 14.00
}

View File

@ -0,0 +1,56 @@
{
"add_sample_data": 1,
"bank_account": "HDFC",
"company_abbr": "GT",
"company_name": "For Testing",
"company_tagline": "Just for GST",
"country": "India",
"currency": "INR",
"customer_1": "Test Customer 1",
"customer_2": "Test Customer 2",
"domain": "Manufacturing",
"email": "great@example.com",
"full_name": "Great Tester",
"fy_end_date": "2018-03-31",
"fy_start_date": "2017-04-01",
"is_purchase_item_1": 1,
"is_purchase_item_2": 1,
"is_purchase_item_3": 0,
"is_purchase_item_4": 0,
"is_purchase_item_5": 0,
"is_sales_item_1": 1,
"is_sales_item_2": 1,
"is_sales_item_3": 1,
"is_sales_item_4": 1,
"is_sales_item_5": 1,
"item_1": "Test Item 1",
"item_2": "Test Item 2",
"item_group_1": "Products",
"item_group_2": "Products",
"item_group_3": "Products",
"item_group_4": "Products",
"item_group_5": "Products",
"item_uom_1": "Unit",
"item_uom_2": "Unit",
"item_uom_3": "Unit",
"item_uom_4": "Unit",
"item_uom_5": "Unit",
"language": "English (United States)",
"password": "test",
"setup_website": 1,
"supplier_1": "Test Supplier 1",
"supplier_2": "Test Supplier 2",
"timezone": "Asia/Kolkata",
"user_accountant_1": 1,
"user_accountant_2": 1,
"user_accountant_3": 1,
"user_accountant_4": 1,
"user_purchaser_1": 1,
"user_purchaser_2": 1,
"user_purchaser_3": 1,
"user_purchaser_4": 1,
"user_sales_1": 1,
"user_sales_2": 1,
"user_sales_3": 1,
"user_sales_4": 1
}

View File

@ -84,7 +84,7 @@ def create_fiscal_year_and_company(args):
if (args.get('company_name')):
frappe.get_doc({
"doctype":"Company",
'company_name':args.get('company_name').strip(),
'company_name':args.get('company_name'),
'enable_perpetual_inventory': 1,
'abbr':args.get('company_abbr'),
'default_currency':args.get('currency'),
@ -104,7 +104,7 @@ def enable_shopping_cart(args):
frappe.get_doc({
"doctype": "Shopping Cart Settings",
"enabled": 1,
'company': args.get('company_name').strip(),
'company': args.get('company_name') ,
'price_list': frappe.db.get_value("Price List", {"selling": 1}),
'default_customer_group': _("Individual"),
'quotation_series': "QTN-",
@ -112,7 +112,7 @@ def enable_shopping_cart(args):
def create_bank_account(args):
if args.get("bank_account"):
company_name = args.get('company_name').strip()
company_name = args.get('company_name')
bank_account_group = frappe.db.get_value("Account",
{"account_type": "Bank", "is_group": 1, "root_type": "Asset",
"company": company_name})
@ -152,7 +152,7 @@ def set_defaults(args):
global_defaults.update({
'current_fiscal_year': args.curr_fiscal_year,
'default_currency': args.get('currency'),
'default_company':args.get('company_name').strip(),
'default_company':args.get('company_name') ,
"country": args.get("country"),
})
@ -253,8 +253,10 @@ def create_sales_tax(args):
country_wise_tax = get_country_wise_tax(args.get("country"))
if country_wise_tax and len(country_wise_tax) > 0:
for sales_tax, tax_data in country_wise_tax.items():
make_tax_account_and_template(args.get("company_name").strip(),
tax_data.get('account_name'), tax_data.get('tax_rate'), sales_tax)
make_tax_account_and_template(
args.get("company_name"),
tax_data.get('account_name'),
tax_data.get('tax_rate'), sales_tax)
def get_country_wise_tax(country):
data = {}
@ -270,13 +272,20 @@ def create_taxes(args):
tax_rate = cstr(args.get("tax_rate_" + str(i)) or "").replace("%", "")
account_name = args.get("tax_" + str(i))
make_tax_account_and_template(args.get("company_name").strip(), account_name, tax_rate)
make_tax_account_and_template(args.get("company_name") , account_name, tax_rate)
def make_tax_account_and_template(company, account_name, tax_rate, template_name=None):
try:
account = make_tax_account(company, account_name, tax_rate)
if account:
make_sales_and_purchase_tax_templates(account, template_name)
if not isinstance(account_name, (list, tuple)):
account_name = [account_name]
tax_rate = [tax_rate]
accounts = []
for i, name in enumerate(account_name):
accounts.append(make_tax_account(company, account_name[i], tax_rate[i]))
if accounts:
make_sales_and_purchase_tax_templates(accounts, template_name)
except frappe.NameError, e:
if e.args[2][0]==1062:
pass
@ -309,30 +318,34 @@ def make_tax_account(company, account_name, tax_rate):
"tax_rate": flt(tax_rate) if tax_rate else None
}).insert(ignore_permissions=True)
def make_sales_and_purchase_tax_templates(account, template_name=None):
def make_sales_and_purchase_tax_templates(accounts, template_name=None):
if not template_name:
template_name = account.name
template_name = accounts[0].name
sales_tax_template = {
"doctype": "Sales Taxes and Charges Template",
"title": template_name,
"company": account.company,
"taxes": [{
"company": accounts[0].company,
'taxes': []
}
for account in accounts:
sales_tax_template['taxes'].append({
"category": "Valuation and Total",
"charge_type": "On Net Total",
"account_head": account.name,
"description": "{0} @ {1}".format(account.account_name, account.tax_rate),
"rate": account.tax_rate
}]
}
})
# Sales
frappe.get_doc(copy.deepcopy(sales_tax_template)).insert(ignore_permissions=True)
# Purchase
purchase_tax_template = copy.deepcopy(sales_tax_template)
purchase_tax_template["doctype"] = "Purchase Taxes and Charges Template"
frappe.get_doc(purchase_tax_template).insert(ignore_permissions=True)
doc = frappe.get_doc(purchase_tax_template)
doc.insert(ignore_permissions=True)
def create_items(args):
for i in xrange(1,6):
@ -346,7 +359,7 @@ def create_items(args):
if is_stock_item:
default_warehouse = frappe.db.get_value("Warehouse", filters={
"warehouse_name": _("Finished Goods") if is_sales_item else _("Stores"),
"company": args.get("company_name").strip()
"company": args.get("company_name")
})
try:
@ -405,7 +418,7 @@ def create_customers(args):
"customer_type": "Company",
"customer_group": _("Commercial"),
"territory": args.get("country"),
"company": args.get("company_name").strip()
"company": args.get("company_name")
}).insert()
if args.get("customer_contact_" + str(i)):
@ -423,7 +436,7 @@ def create_suppliers(args):
"doctype":"Supplier",
"supplier_name": supplier,
"supplier_type": _("Local"),
"company": args.get("company_name").strip()
"company": args.get("company_name")
}).insert()
if args.get("supplier_contact_" + str(i)):
@ -434,7 +447,7 @@ def create_suppliers(args):
def create_contact(contact, party_type, party):
"""Create contact based on given contact name"""
contact = contact.strip().split(" ")
contact = contact .split(" ")
contact = frappe.get_doc({
"doctype":"Contact",
@ -466,7 +479,7 @@ def create_logo(args):
fileurl = save_file(filename, content, "Website Settings", "Website Settings",
decode=True).file_url
frappe.db.set_value("Website Settings", "Website Settings", "brand_html",
"<img src='{0}' style='max-width: 40px; max-height: 25px;'> {1}".format(fileurl, args.get("company_name").strip()))
"<img src='{0}' style='max-width: 40px; max-height: 25px;'> {1}".format(fileurl, args.get("company_name") ))
def create_territories():
"""create two default territories, one for home country and one named Rest of the World"""

File diff suppressed because one or more lines are too long

View File

@ -1,15 +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
from erpnext.setup.setup_wizard.test_setup_data import args
from frappe.desk.page.setup_wizard.setup_wizard import setup_complete
import frappe.utils.scheduler
if __name__=="__main__":
frappe.connect()
frappe.local.form_dict = frappe._dict(args)
setup_complete()
frappe.utils.scheduler.disable_scheduler()

View File

@ -0,0 +1,15 @@
import json, os
from frappe.desk.page.setup_wizard.setup_wizard import setup_complete
from erpnext.setup.setup_wizard import setup_wizard
def complete():
with open(os.path.join(os.path.dirname(__file__),
'data', 'test_mfg.json'), 'r') as f:
data = json.loads(f.read())
#setup_wizard.create_sales_tax(data)
setup_complete(data)