Merge branch 'develop' of https://github.com/frappe/erpnext into develop
This commit is contained in:
commit
7f1e4a29c5
@ -14,7 +14,7 @@ install:
|
|||||||
- sudo apt-get update
|
- sudo apt-get update
|
||||||
- sudo apt-get purge -y mysql-common
|
- sudo apt-get purge -y mysql-common
|
||||||
- sudo apt-get install mariadb-server mariadb-common libmariadbclient-dev
|
- sudo apt-get install mariadb-server mariadb-common libmariadbclient-dev
|
||||||
- CFLAGS=-O0 pip install git+https://github.com/frappe/frappe.git@$TRAVIS_BRANCH &&
|
- CFLAGS=-O0 pip install git+https://github.com/frappe/frappe.git@$develop &&
|
||||||
- pip install --editable .
|
- pip install --editable .
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
|
|||||||
@ -55,12 +55,12 @@ class CForm(Document):
|
|||||||
|
|
||||||
def get_invoice_details(self, invoice_no):
|
def get_invoice_details(self, invoice_no):
|
||||||
""" Pull details from invoices for referrence """
|
""" Pull details from invoices for referrence """
|
||||||
|
if invoice_no:
|
||||||
inv = frappe.db.get_value("Sales Invoice", invoice_no,
|
inv = frappe.db.get_value("Sales Invoice", invoice_no,
|
||||||
["posting_date", "territory", "net_total", "grand_total"], as_dict=True)
|
["posting_date", "territory", "net_total", "grand_total"], as_dict=True)
|
||||||
return {
|
return {
|
||||||
'invoice_date' : inv.posting_date,
|
'invoice_date' : inv.posting_date,
|
||||||
'territory' : inv.territory,
|
'territory' : inv.territory,
|
||||||
'net_total' : inv.net_total,
|
'net_total' : inv.net_total,
|
||||||
'grand_total' : inv.grand_total
|
'grand_total' : inv.grand_total
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,7 +55,7 @@
|
|||||||
],
|
],
|
||||||
"icon": "icon-calendar",
|
"icon": "icon-calendar",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"modified": "2014-05-27 03:49:10.942338",
|
"modified": "2014-07-14 05:30:56.843180",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Fiscal Year",
|
"name": "Fiscal Year",
|
||||||
@ -82,5 +82,7 @@
|
|||||||
"read": 1,
|
"read": 1,
|
||||||
"role": "All"
|
"role": "All"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"sort_field": "name",
|
||||||
|
"sort_order": "DESC"
|
||||||
}
|
}
|
||||||
@ -183,7 +183,7 @@ def get_pricing_rules(args):
|
|||||||
group_condition = _get_tree_conditions(parenttype)
|
group_condition = _get_tree_conditions(parenttype)
|
||||||
if group_condition:
|
if group_condition:
|
||||||
conditions += " and " + group_condition
|
conditions += " and " + group_condition
|
||||||
|
if not args.price_list: args.price_list = None
|
||||||
conditions += " and ifnull(for_price_list, '') in (%(price_list)s, '')"
|
conditions += " and ifnull(for_price_list, '') in (%(price_list)s, '')"
|
||||||
|
|
||||||
if args.get("transaction_date"):
|
if args.get("transaction_date"):
|
||||||
|
|||||||
@ -30,6 +30,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
'target_ref_field': 'amount',
|
'target_ref_field': 'amount',
|
||||||
'source_field': 'amount',
|
'source_field': 'amount',
|
||||||
'percent_join_field': 'purchase_order',
|
'percent_join_field': 'purchase_order',
|
||||||
|
'overflow_type': 'billing'
|
||||||
}]
|
}]
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
|||||||
@ -36,7 +36,8 @@ class SalesInvoice(SellingController):
|
|||||||
'join_field': 'so_detail',
|
'join_field': 'so_detail',
|
||||||
'percent_join_field': 'sales_order',
|
'percent_join_field': 'sales_order',
|
||||||
'status_field': 'billing_status',
|
'status_field': 'billing_status',
|
||||||
'keyword': 'Billed'
|
'keyword': 'Billed',
|
||||||
|
'overflow_type': 'billing'
|
||||||
}]
|
}]
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
@ -134,7 +135,8 @@ class SalesInvoice(SellingController):
|
|||||||
'keyword':'Delivered',
|
'keyword':'Delivered',
|
||||||
'second_source_dt': 'Delivery Note Item',
|
'second_source_dt': 'Delivery Note Item',
|
||||||
'second_source_field': 'qty',
|
'second_source_field': 'qty',
|
||||||
'second_join_field': 'prevdoc_detail_docname'
|
'second_join_field': 'prevdoc_detail_docname',
|
||||||
|
'overflow_type': 'delivery'
|
||||||
})
|
})
|
||||||
|
|
||||||
def on_update_after_submit(self):
|
def on_update_after_submit(self):
|
||||||
@ -339,8 +341,8 @@ class SalesInvoice(SellingController):
|
|||||||
|
|
||||||
def validate_pos(self):
|
def validate_pos(self):
|
||||||
if not self.cash_bank_account and flt(self.paid_amount):
|
if not self.cash_bank_account and flt(self.paid_amount):
|
||||||
msgprint(_("Cash or Bank Account is mandatory for making payment entry"))
|
frappe.throw(_("Cash or Bank Account is mandatory for making payment entry"))
|
||||||
raise Exception
|
|
||||||
if flt(self.paid_amount) + flt(self.write_off_amount) \
|
if flt(self.paid_amount) + flt(self.write_off_amount) \
|
||||||
- flt(self.grand_total) > 1/(10**(self.precision("grand_total") + 1)):
|
- flt(self.grand_total) > 1/(10**(self.precision("grand_total") + 1)):
|
||||||
frappe.throw(_("""Paid amount + Write Off Amount can not be greater than Grand Total"""))
|
frappe.throw(_("""Paid amount + Write Off Amount can not be greater than Grand Total"""))
|
||||||
@ -431,9 +433,8 @@ class SalesInvoice(SellingController):
|
|||||||
submitted = frappe.db.sql("""select name from `tabSales Order`
|
submitted = frappe.db.sql("""select name from `tabSales Order`
|
||||||
where docstatus = 1 and name = %s""", d.sales_order)
|
where docstatus = 1 and name = %s""", d.sales_order)
|
||||||
if not submitted:
|
if not submitted:
|
||||||
msgprint(_("Sales Order {0} is not submitted").format(d.sales_order))
|
frappe.throw(_("Sales Order {0} is not submitted").format(d.sales_order))
|
||||||
raise Exception
|
|
||||||
|
|
||||||
if d.delivery_note:
|
if d.delivery_note:
|
||||||
submitted = frappe.db.sql("""select name from `tabDelivery Note`
|
submitted = frappe.db.sql("""select name from `tabDelivery Note`
|
||||||
where docstatus = 1 and name = %s""", d.delivery_note)
|
where docstatus = 1 and name = %s""", d.delivery_note)
|
||||||
@ -682,7 +683,7 @@ def manage_recurring_invoices(next_date=None, commit=True):
|
|||||||
|
|
||||||
if exception_list:
|
if exception_list:
|
||||||
exception_message = "\n\n".join([cstr(d) for d in exception_list])
|
exception_message = "\n\n".join([cstr(d) for d in exception_list])
|
||||||
raise Exception, exception_message
|
frappe.throw(exception_message)
|
||||||
|
|
||||||
def make_new_invoice(ref_wrapper, posting_date):
|
def make_new_invoice(ref_wrapper, posting_date):
|
||||||
from erpnext.accounts.utils import get_fiscal_year
|
from erpnext.accounts.utils import get_fiscal_year
|
||||||
|
|||||||
@ -1,385 +1,385 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"company": "_Test Company",
|
"company": "_Test Company",
|
||||||
"conversion_rate": 1.0,
|
"conversion_rate": 1.0,
|
||||||
"currency": "INR",
|
"currency": "INR",
|
||||||
"customer": "_Test Customer",
|
"customer": "_Test Customer",
|
||||||
"customer_name": "_Test Customer",
|
"customer_name": "_Test Customer",
|
||||||
"debit_to": "_Test Customer - _TC",
|
"debit_to": "_Test Customer - _TC",
|
||||||
"doctype": "Sales Invoice",
|
"doctype": "Sales Invoice",
|
||||||
"due_date": "2013-01-23",
|
"due_date": "2013-01-23",
|
||||||
"entries": [
|
"entries": [
|
||||||
{
|
{
|
||||||
"amount": 500.0,
|
"amount": 500.0,
|
||||||
"base_amount": 500.0,
|
"base_amount": 500.0,
|
||||||
"base_rate": 500.0,
|
"base_rate": 500.0,
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"description": "138-CMS Shoe",
|
"description": "138-CMS Shoe",
|
||||||
"doctype": "Sales Invoice Item",
|
"doctype": "Sales Invoice Item",
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"item_name": "138-CMS Shoe",
|
"item_name": "138-CMS Shoe",
|
||||||
"parentfield": "entries",
|
"parentfield": "entries",
|
||||||
"qty": 1.0,
|
"qty": 1.0,
|
||||||
"rate": 500.0
|
"rate": 500.0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"fiscal_year": "_Test Fiscal Year 2013",
|
"fiscal_year": "_Test Fiscal Year 2013",
|
||||||
"grand_total": 561.8,
|
"grand_total": 561.8,
|
||||||
"grand_total_export": 561.8,
|
"grand_total_export": 561.8,
|
||||||
"is_pos": 0,
|
"is_pos": 0,
|
||||||
"naming_series": "_T-Sales Invoice-",
|
"naming_series": "_T-Sales Invoice-",
|
||||||
"net_total": 500.0,
|
"net_total": 500.0,
|
||||||
"other_charges": [
|
"other_charges": [
|
||||||
{
|
{
|
||||||
"account_head": "_Test Account VAT - _TC",
|
"account_head": "_Test Account VAT - _TC",
|
||||||
"charge_type": "On Net Total",
|
"charge_type": "On Net Total",
|
||||||
"description": "VAT",
|
"description": "VAT",
|
||||||
"doctype": "Sales Taxes and Charges",
|
"doctype": "Sales Taxes and Charges",
|
||||||
"parentfield": "other_charges",
|
"parentfield": "other_charges",
|
||||||
"rate": 6
|
"rate": 6
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"account_head": "_Test Account Service Tax - _TC",
|
"account_head": "_Test Account Service Tax - _TC",
|
||||||
"charge_type": "On Net Total",
|
"charge_type": "On Net Total",
|
||||||
"description": "Service Tax",
|
"description": "Service Tax",
|
||||||
"doctype": "Sales Taxes and Charges",
|
"doctype": "Sales Taxes and Charges",
|
||||||
"parentfield": "other_charges",
|
"parentfield": "other_charges",
|
||||||
"rate": 6.36
|
"rate": 6.36
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"plc_conversion_rate": 1.0,
|
"plc_conversion_rate": 1.0,
|
||||||
"posting_date": "2013-01-23",
|
"posting_date": "2013-01-23",
|
||||||
"price_list_currency": "INR",
|
"price_list_currency": "INR",
|
||||||
"sales_team": [
|
"sales_team": [
|
||||||
{
|
{
|
||||||
"allocated_percentage": 65.5,
|
"allocated_percentage": 65.5,
|
||||||
"doctype": "Sales Team",
|
"doctype": "Sales Team",
|
||||||
"parentfield": "sales_team",
|
"parentfield": "sales_team",
|
||||||
"sales_person": "_Test Sales Person 1"
|
"sales_person": "_Test Sales Person 1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allocated_percentage": 34.5,
|
"allocated_percentage": 34.5,
|
||||||
"doctype": "Sales Team",
|
"doctype": "Sales Team",
|
||||||
"parentfield": "sales_team",
|
"parentfield": "sales_team",
|
||||||
"sales_person": "_Test Sales Person 2"
|
"sales_person": "_Test Sales Person 2"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"selling_price_list": "_Test Price List",
|
"selling_price_list": "_Test Price List",
|
||||||
"territory": "_Test Territory"
|
"territory": "_Test Territory"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"company": "_Test Company",
|
"company": "_Test Company",
|
||||||
"conversion_rate": 1.0,
|
"conversion_rate": 1.0,
|
||||||
"currency": "INR",
|
"currency": "INR",
|
||||||
"customer": "_Test Customer",
|
"customer": "_Test Customer",
|
||||||
"customer_name": "_Test Customer",
|
"customer_name": "_Test Customer",
|
||||||
"debit_to": "_Test Customer - _TC",
|
"debit_to": "_Test Customer - _TC",
|
||||||
"doctype": "Sales Invoice",
|
"doctype": "Sales Invoice",
|
||||||
"due_date": "2013-01-23",
|
"due_date": "2013-03-07",
|
||||||
"entries": [
|
"entries": [
|
||||||
{
|
{
|
||||||
"amount": 500.0,
|
"amount": 500.0,
|
||||||
"base_amount": 500.0,
|
"base_amount": 500.0,
|
||||||
"base_rate": 500.0,
|
"base_rate": 500.0,
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"description": "_Test Item",
|
"description": "_Test Item",
|
||||||
"doctype": "Sales Invoice Item",
|
"doctype": "Sales Invoice Item",
|
||||||
"expense_account": "_Test Account Cost for Goods Sold - _TC",
|
"expense_account": "_Test Account Cost for Goods Sold - _TC",
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"item_code": "_Test Item",
|
"item_code": "_Test Item",
|
||||||
"item_name": "_Test Item",
|
"item_name": "_Test Item",
|
||||||
"parentfield": "entries",
|
"parentfield": "entries",
|
||||||
"price_list_rate": 500.0,
|
"price_list_rate": 500.0,
|
||||||
"qty": 1.0
|
"qty": 1.0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"fiscal_year": "_Test Fiscal Year 2013",
|
"fiscal_year": "_Test Fiscal Year 2013",
|
||||||
"grand_total": 630.0,
|
"grand_total": 630.0,
|
||||||
"grand_total_export": 630.0,
|
"grand_total_export": 630.0,
|
||||||
"is_pos": 0,
|
"is_pos": 0,
|
||||||
"naming_series": "_T-Sales Invoice-",
|
"naming_series": "_T-Sales Invoice-",
|
||||||
"net_total": 500.0,
|
"net_total": 500.0,
|
||||||
"other_charges": [
|
"other_charges": [
|
||||||
{
|
{
|
||||||
"account_head": "_Test Account VAT - _TC",
|
"account_head": "_Test Account VAT - _TC",
|
||||||
"charge_type": "On Net Total",
|
"charge_type": "On Net Total",
|
||||||
"description": "VAT",
|
"description": "VAT",
|
||||||
"doctype": "Sales Taxes and Charges",
|
"doctype": "Sales Taxes and Charges",
|
||||||
"parentfield": "other_charges",
|
"parentfield": "other_charges",
|
||||||
"rate": 16
|
"rate": 16
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"account_head": "_Test Account Service Tax - _TC",
|
"account_head": "_Test Account Service Tax - _TC",
|
||||||
"charge_type": "On Net Total",
|
"charge_type": "On Net Total",
|
||||||
"description": "Service Tax",
|
"description": "Service Tax",
|
||||||
"doctype": "Sales Taxes and Charges",
|
"doctype": "Sales Taxes and Charges",
|
||||||
"parentfield": "other_charges",
|
"parentfield": "other_charges",
|
||||||
"rate": 10
|
"rate": 10
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"plc_conversion_rate": 1.0,
|
"plc_conversion_rate": 1.0,
|
||||||
"posting_date": "2013-03-07",
|
"posting_date": "2013-03-07",
|
||||||
"price_list_currency": "INR",
|
"price_list_currency": "INR",
|
||||||
"selling_price_list": "_Test Price List",
|
"selling_price_list": "_Test Price List",
|
||||||
"territory": "_Test Territory"
|
"territory": "_Test Territory"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"company": "_Test Company",
|
"company": "_Test Company",
|
||||||
"conversion_rate": 1.0,
|
"conversion_rate": 1.0,
|
||||||
"currency": "INR",
|
"currency": "INR",
|
||||||
"customer": "_Test Customer",
|
"customer": "_Test Customer",
|
||||||
"customer_name": "_Test Customer",
|
"customer_name": "_Test Customer",
|
||||||
"debit_to": "_Test Customer - _TC",
|
"debit_to": "_Test Customer - _TC",
|
||||||
"doctype": "Sales Invoice",
|
"doctype": "Sales Invoice",
|
||||||
"due_date": "2013-01-23",
|
"due_date": "2013-01-23",
|
||||||
"entries": [
|
"entries": [
|
||||||
{
|
{
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"doctype": "Sales Invoice Item",
|
"doctype": "Sales Invoice Item",
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"item_code": "_Test Item Home Desktop 100",
|
"item_code": "_Test Item Home Desktop 100",
|
||||||
"item_name": "_Test Item Home Desktop 100",
|
"item_name": "_Test Item Home Desktop 100",
|
||||||
"item_tax_rate": "{\"_Test Account Excise Duty - _TC\": 10}",
|
"item_tax_rate": "{\"_Test Account Excise Duty - _TC\": 10}",
|
||||||
"parentfield": "entries",
|
"parentfield": "entries",
|
||||||
"price_list_rate": 50,
|
"price_list_rate": 50,
|
||||||
"qty": 10,
|
"qty": 10,
|
||||||
"rate": 50,
|
"rate": 50,
|
||||||
"stock_uom": "_Test UOM"
|
"stock_uom": "_Test UOM"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"doctype": "Sales Invoice Item",
|
"doctype": "Sales Invoice Item",
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"item_code": "_Test Item Home Desktop 200",
|
"item_code": "_Test Item Home Desktop 200",
|
||||||
"item_name": "_Test Item Home Desktop 200",
|
"item_name": "_Test Item Home Desktop 200",
|
||||||
"parentfield": "entries",
|
"parentfield": "entries",
|
||||||
"price_list_rate": 150,
|
"price_list_rate": 150,
|
||||||
"qty": 5,
|
"qty": 5,
|
||||||
"rate": 150,
|
"rate": 150,
|
||||||
"stock_uom": "_Test UOM"
|
"stock_uom": "_Test UOM"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"fiscal_year": "_Test Fiscal Year 2013",
|
"fiscal_year": "_Test Fiscal Year 2013",
|
||||||
"grand_total_export": 0,
|
"grand_total_export": 0,
|
||||||
"is_pos": 0,
|
"is_pos": 0,
|
||||||
"naming_series": "_T-Sales Invoice-",
|
"naming_series": "_T-Sales Invoice-",
|
||||||
"other_charges": [
|
"other_charges": [
|
||||||
{
|
{
|
||||||
"account_head": "_Test Account Shipping Charges - _TC",
|
"account_head": "_Test Account Shipping Charges - _TC",
|
||||||
"charge_type": "Actual",
|
"charge_type": "Actual",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"description": "Shipping Charges",
|
"description": "Shipping Charges",
|
||||||
"doctype": "Sales Taxes and Charges",
|
"doctype": "Sales Taxes and Charges",
|
||||||
"parentfield": "other_charges",
|
"parentfield": "other_charges",
|
||||||
"rate": 100
|
"rate": 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"account_head": "_Test Account Customs Duty - _TC",
|
"account_head": "_Test Account Customs Duty - _TC",
|
||||||
"charge_type": "On Net Total",
|
"charge_type": "On Net Total",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"description": "Customs Duty",
|
"description": "Customs Duty",
|
||||||
"doctype": "Sales Taxes and Charges",
|
"doctype": "Sales Taxes and Charges",
|
||||||
"parentfield": "other_charges",
|
"parentfield": "other_charges",
|
||||||
"rate": 10
|
"rate": 10
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"account_head": "_Test Account Excise Duty - _TC",
|
"account_head": "_Test Account Excise Duty - _TC",
|
||||||
"charge_type": "On Net Total",
|
"charge_type": "On Net Total",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"description": "Excise Duty",
|
"description": "Excise Duty",
|
||||||
"doctype": "Sales Taxes and Charges",
|
"doctype": "Sales Taxes and Charges",
|
||||||
"parentfield": "other_charges",
|
"parentfield": "other_charges",
|
||||||
"rate": 12
|
"rate": 12
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"account_head": "_Test Account Education Cess - _TC",
|
"account_head": "_Test Account Education Cess - _TC",
|
||||||
"charge_type": "On Previous Row Amount",
|
"charge_type": "On Previous Row Amount",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"description": "Education Cess",
|
"description": "Education Cess",
|
||||||
"doctype": "Sales Taxes and Charges",
|
"doctype": "Sales Taxes and Charges",
|
||||||
"parentfield": "other_charges",
|
"parentfield": "other_charges",
|
||||||
"rate": 2,
|
"rate": 2,
|
||||||
"row_id": 3
|
"row_id": 3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"account_head": "_Test Account S&H Education Cess - _TC",
|
"account_head": "_Test Account S&H Education Cess - _TC",
|
||||||
"charge_type": "On Previous Row Amount",
|
"charge_type": "On Previous Row Amount",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"description": "S&H Education Cess",
|
"description": "S&H Education Cess",
|
||||||
"doctype": "Sales Taxes and Charges",
|
"doctype": "Sales Taxes and Charges",
|
||||||
"parentfield": "other_charges",
|
"parentfield": "other_charges",
|
||||||
"rate": 1,
|
"rate": 1,
|
||||||
"row_id": 3
|
"row_id": 3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"account_head": "_Test Account CST - _TC",
|
"account_head": "_Test Account CST - _TC",
|
||||||
"charge_type": "On Previous Row Total",
|
"charge_type": "On Previous Row Total",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"description": "CST",
|
"description": "CST",
|
||||||
"doctype": "Sales Taxes and Charges",
|
"doctype": "Sales Taxes and Charges",
|
||||||
"parentfield": "other_charges",
|
"parentfield": "other_charges",
|
||||||
"rate": 2,
|
"rate": 2,
|
||||||
"row_id": 5
|
"row_id": 5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"account_head": "_Test Account VAT - _TC",
|
"account_head": "_Test Account VAT - _TC",
|
||||||
"charge_type": "On Net Total",
|
"charge_type": "On Net Total",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"description": "VAT",
|
"description": "VAT",
|
||||||
"doctype": "Sales Taxes and Charges",
|
"doctype": "Sales Taxes and Charges",
|
||||||
"parentfield": "other_charges",
|
"parentfield": "other_charges",
|
||||||
"rate": 12.5
|
"rate": 12.5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"account_head": "_Test Account Discount - _TC",
|
"account_head": "_Test Account Discount - _TC",
|
||||||
"charge_type": "On Previous Row Total",
|
"charge_type": "On Previous Row Total",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"description": "Discount",
|
"description": "Discount",
|
||||||
"doctype": "Sales Taxes and Charges",
|
"doctype": "Sales Taxes and Charges",
|
||||||
"parentfield": "other_charges",
|
"parentfield": "other_charges",
|
||||||
"rate": -10,
|
"rate": -10,
|
||||||
"row_id": 7
|
"row_id": 7
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"plc_conversion_rate": 1.0,
|
"plc_conversion_rate": 1.0,
|
||||||
"posting_date": "2013-01-23",
|
"posting_date": "2013-01-23",
|
||||||
"price_list_currency": "INR",
|
"price_list_currency": "INR",
|
||||||
"selling_price_list": "_Test Price List",
|
"selling_price_list": "_Test Price List",
|
||||||
"territory": "_Test Territory"
|
"territory": "_Test Territory"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"company": "_Test Company",
|
"company": "_Test Company",
|
||||||
"conversion_rate": 1.0,
|
"conversion_rate": 1.0,
|
||||||
"currency": "INR",
|
"currency": "INR",
|
||||||
"customer": "_Test Customer",
|
"customer": "_Test Customer",
|
||||||
"customer_name": "_Test Customer",
|
"customer_name": "_Test Customer",
|
||||||
"debit_to": "_Test Customer - _TC",
|
"debit_to": "_Test Customer - _TC",
|
||||||
"doctype": "Sales Invoice",
|
"doctype": "Sales Invoice",
|
||||||
"due_date": "2013-01-23",
|
"due_date": "2013-01-23",
|
||||||
"entries": [
|
"entries": [
|
||||||
{
|
{
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"doctype": "Sales Invoice Item",
|
"doctype": "Sales Invoice Item",
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"item_code": "_Test Item Home Desktop 100",
|
"item_code": "_Test Item Home Desktop 100",
|
||||||
"item_name": "_Test Item Home Desktop 100",
|
"item_name": "_Test Item Home Desktop 100",
|
||||||
"item_tax_rate": "{\"_Test Account Excise Duty - _TC\": 10}",
|
"item_tax_rate": "{\"_Test Account Excise Duty - _TC\": 10}",
|
||||||
"parentfield": "entries",
|
"parentfield": "entries",
|
||||||
"price_list_rate": 62.5,
|
"price_list_rate": 62.5,
|
||||||
"qty": 10,
|
"qty": 10,
|
||||||
"stock_uom": "_Test UOM"
|
"stock_uom": "_Test UOM"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"doctype": "Sales Invoice Item",
|
"doctype": "Sales Invoice Item",
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"item_code": "_Test Item Home Desktop 200",
|
"item_code": "_Test Item Home Desktop 200",
|
||||||
"item_name": "_Test Item Home Desktop 200",
|
"item_name": "_Test Item Home Desktop 200",
|
||||||
"parentfield": "entries",
|
"parentfield": "entries",
|
||||||
"price_list_rate": 190.66,
|
"price_list_rate": 190.66,
|
||||||
"qty": 5,
|
"qty": 5,
|
||||||
"stock_uom": "_Test UOM"
|
"stock_uom": "_Test UOM"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"fiscal_year": "_Test Fiscal Year 2013",
|
"fiscal_year": "_Test Fiscal Year 2013",
|
||||||
"grand_total_export": 0,
|
"grand_total_export": 0,
|
||||||
"is_pos": 0,
|
"is_pos": 0,
|
||||||
"naming_series": "_T-Sales Invoice-",
|
"naming_series": "_T-Sales Invoice-",
|
||||||
"other_charges": [
|
"other_charges": [
|
||||||
{
|
{
|
||||||
"account_head": "_Test Account Excise Duty - _TC",
|
"account_head": "_Test Account Excise Duty - _TC",
|
||||||
"charge_type": "On Net Total",
|
"charge_type": "On Net Total",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"description": "Excise Duty",
|
"description": "Excise Duty",
|
||||||
"doctype": "Sales Taxes and Charges",
|
"doctype": "Sales Taxes and Charges",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"included_in_print_rate": 1,
|
"included_in_print_rate": 1,
|
||||||
"parentfield": "other_charges",
|
"parentfield": "other_charges",
|
||||||
"rate": 12
|
"rate": 12
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"account_head": "_Test Account Education Cess - _TC",
|
"account_head": "_Test Account Education Cess - _TC",
|
||||||
"charge_type": "On Previous Row Amount",
|
"charge_type": "On Previous Row Amount",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"description": "Education Cess",
|
"description": "Education Cess",
|
||||||
"doctype": "Sales Taxes and Charges",
|
"doctype": "Sales Taxes and Charges",
|
||||||
"idx": 2,
|
"idx": 2,
|
||||||
"included_in_print_rate": 1,
|
"included_in_print_rate": 1,
|
||||||
"parentfield": "other_charges",
|
"parentfield": "other_charges",
|
||||||
"rate": 2,
|
"rate": 2,
|
||||||
"row_id": 1
|
"row_id": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"account_head": "_Test Account S&H Education Cess - _TC",
|
"account_head": "_Test Account S&H Education Cess - _TC",
|
||||||
"charge_type": "On Previous Row Amount",
|
"charge_type": "On Previous Row Amount",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"description": "S&H Education Cess",
|
"description": "S&H Education Cess",
|
||||||
"doctype": "Sales Taxes and Charges",
|
"doctype": "Sales Taxes and Charges",
|
||||||
"idx": 3,
|
"idx": 3,
|
||||||
"included_in_print_rate": 1,
|
"included_in_print_rate": 1,
|
||||||
"parentfield": "other_charges",
|
"parentfield": "other_charges",
|
||||||
"rate": 1,
|
"rate": 1,
|
||||||
"row_id": 1
|
"row_id": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"account_head": "_Test Account CST - _TC",
|
"account_head": "_Test Account CST - _TC",
|
||||||
"charge_type": "On Previous Row Total",
|
"charge_type": "On Previous Row Total",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"description": "CST",
|
"description": "CST",
|
||||||
"doctype": "Sales Taxes and Charges",
|
"doctype": "Sales Taxes and Charges",
|
||||||
"idx": 4,
|
"idx": 4,
|
||||||
"included_in_print_rate": 1,
|
"included_in_print_rate": 1,
|
||||||
"parentfield": "other_charges",
|
"parentfield": "other_charges",
|
||||||
"rate": 2,
|
"rate": 2,
|
||||||
"row_id": 3
|
"row_id": 3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"account_head": "_Test Account VAT - _TC",
|
"account_head": "_Test Account VAT - _TC",
|
||||||
"charge_type": "On Net Total",
|
"charge_type": "On Net Total",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"description": "VAT",
|
"description": "VAT",
|
||||||
"doctype": "Sales Taxes and Charges",
|
"doctype": "Sales Taxes and Charges",
|
||||||
"idx": 5,
|
"idx": 5,
|
||||||
"included_in_print_rate": 1,
|
"included_in_print_rate": 1,
|
||||||
"parentfield": "other_charges",
|
"parentfield": "other_charges",
|
||||||
"rate": 12.5
|
"rate": 12.5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"account_head": "_Test Account Customs Duty - _TC",
|
"account_head": "_Test Account Customs Duty - _TC",
|
||||||
"charge_type": "On Net Total",
|
"charge_type": "On Net Total",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"description": "Customs Duty",
|
"description": "Customs Duty",
|
||||||
"doctype": "Sales Taxes and Charges",
|
"doctype": "Sales Taxes and Charges",
|
||||||
"idx": 6,
|
"idx": 6,
|
||||||
"parentfield": "other_charges",
|
"parentfield": "other_charges",
|
||||||
"rate": 10
|
"rate": 10
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"account_head": "_Test Account Shipping Charges - _TC",
|
"account_head": "_Test Account Shipping Charges - _TC",
|
||||||
"charge_type": "Actual",
|
"charge_type": "Actual",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"description": "Shipping Charges",
|
"description": "Shipping Charges",
|
||||||
"doctype": "Sales Taxes and Charges",
|
"doctype": "Sales Taxes and Charges",
|
||||||
"idx": 7,
|
"idx": 7,
|
||||||
"parentfield": "other_charges",
|
"parentfield": "other_charges",
|
||||||
"rate": 100
|
"rate": 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"account_head": "_Test Account Discount - _TC",
|
"account_head": "_Test Account Discount - _TC",
|
||||||
"charge_type": "On Previous Row Total",
|
"charge_type": "On Previous Row Total",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"description": "Discount",
|
"description": "Discount",
|
||||||
"doctype": "Sales Taxes and Charges",
|
"doctype": "Sales Taxes and Charges",
|
||||||
"idx": 8,
|
"idx": 8,
|
||||||
"parentfield": "other_charges",
|
"parentfield": "other_charges",
|
||||||
"rate": -10,
|
"rate": -10,
|
||||||
"row_id": 7
|
"row_id": 7
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"plc_conversion_rate": 1.0,
|
"plc_conversion_rate": 1.0,
|
||||||
"posting_date": "2013-01-23",
|
"posting_date": "2013-01-23",
|
||||||
"price_list_currency": "INR",
|
"price_list_currency": "INR",
|
||||||
"selling_price_list": "_Test Price List",
|
"selling_price_list": "_Test Price List",
|
||||||
"territory": "_Test Territory"
|
"territory": "_Test Territory"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@ -674,6 +674,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
"notification_email_address": "test@example.com, test1@example.com, test2@example.com",
|
"notification_email_address": "test@example.com, test1@example.com, test2@example.com",
|
||||||
"repeat_on_day_of_month": getdate(today).day,
|
"repeat_on_day_of_month": getdate(today).day,
|
||||||
"posting_date": today,
|
"posting_date": today,
|
||||||
|
"due_date": None,
|
||||||
"fiscal_year": get_fiscal_year(today)[0],
|
"fiscal_year": get_fiscal_year(today)[0],
|
||||||
"invoice_period_from_date": get_first_day(today),
|
"invoice_period_from_date": get_first_day(today),
|
||||||
"invoice_period_to_date": get_last_day(today)
|
"invoice_period_to_date": get_last_day(today)
|
||||||
|
|||||||
0
erpnext/accounts/report/balance_sheet/__init__.py
Normal file
0
erpnext/accounts/report/balance_sheet/__init__.py
Normal file
1
erpnext/accounts/report/balance_sheet/balance_sheet.html
Normal file
1
erpnext/accounts/report/balance_sheet/balance_sheet.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
{% include "accounts/report/financial_statements.html" %}
|
||||||
6
erpnext/accounts/report/balance_sheet/balance_sheet.js
Normal file
6
erpnext/accounts/report/balance_sheet/balance_sheet.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||||
|
// License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
frappe.require("assets/erpnext/js/financial_statements.js");
|
||||||
|
|
||||||
|
frappe.query_reports["Balance Sheet"] = erpnext.financial_statements;
|
||||||
15
erpnext/accounts/report/balance_sheet/balance_sheet.json
Normal file
15
erpnext/accounts/report/balance_sheet/balance_sheet.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"apply_user_permissions": 1,
|
||||||
|
"creation": "2014-07-14 05:24:20.385279",
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Report",
|
||||||
|
"is_standard": "Yes",
|
||||||
|
"modified": "2014-07-14 05:24:20.385279",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Balance Sheet",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"ref_doctype": "GL Entry",
|
||||||
|
"report_name": "Balance Sheet",
|
||||||
|
"report_type": "Script Report"
|
||||||
|
}
|
||||||
53
erpnext/accounts/report/balance_sheet/balance_sheet.py
Normal file
53
erpnext/accounts/report/balance_sheet/balance_sheet.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
from frappe.utils import flt
|
||||||
|
from erpnext.accounts.report.financial_statements import (process_filters, get_period_list, get_columns, get_data)
|
||||||
|
|
||||||
|
def execute(filters=None):
|
||||||
|
process_filters(filters)
|
||||||
|
period_list = get_period_list(filters.fiscal_year, filters.periodicity, from_beginning=True)
|
||||||
|
|
||||||
|
asset = get_data(filters.company, "Asset", "Debit", period_list, filters.depth)
|
||||||
|
liability = get_data(filters.company, "Liability", "Credit", period_list, filters.depth)
|
||||||
|
equity = get_data(filters.company, "Equity", "Credit", period_list, filters.depth)
|
||||||
|
provisional_profit_loss = get_provisional_profit_loss(asset, liability, equity, period_list)
|
||||||
|
|
||||||
|
data = []
|
||||||
|
data.extend(asset or [])
|
||||||
|
data.extend(liability or [])
|
||||||
|
data.extend(equity or [])
|
||||||
|
if provisional_profit_loss:
|
||||||
|
data.append(provisional_profit_loss)
|
||||||
|
|
||||||
|
columns = get_columns(period_list)
|
||||||
|
|
||||||
|
return columns, data
|
||||||
|
|
||||||
|
def get_provisional_profit_loss(asset, liability, equity, period_list):
|
||||||
|
if asset and (liability or equity):
|
||||||
|
provisional_profit_loss = {
|
||||||
|
"account_name": _("Provisional Profit / Loss (Credit)"),
|
||||||
|
"account": None,
|
||||||
|
"is_profit_loss": True
|
||||||
|
}
|
||||||
|
|
||||||
|
has_value = False
|
||||||
|
|
||||||
|
for period in period_list:
|
||||||
|
effective_liability = 0.0
|
||||||
|
if liability:
|
||||||
|
effective_liability += flt(liability[-2][period.key])
|
||||||
|
if equity:
|
||||||
|
effective_liability += flt(equity[-2][period.key])
|
||||||
|
|
||||||
|
provisional_profit_loss[period.key] = flt(asset[-2][period.key]) - effective_liability
|
||||||
|
|
||||||
|
if provisional_profit_loss[period.key]:
|
||||||
|
has_value = True
|
||||||
|
|
||||||
|
if has_value:
|
||||||
|
return provisional_profit_loss
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
<div style="margin-bottom: 7px;" class="text-center">
|
||||||
|
{%= frappe.boot.letter_heads[frappe.defaults.get_default("letter_head")] %}
|
||||||
|
</div>
|
||||||
|
<h2 class="text-center">{%= __("Bank Reconciliation Statement") %}</h2>
|
||||||
|
<h4 class="text-center">{%= filters.account %}</h3>
|
||||||
|
<hr>
|
||||||
|
<table class="table table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 15%">{%= __("Posting Date") %}</th>
|
||||||
|
<th style="width: 15%">{%= __("Journal Voucher") %}</th>
|
||||||
|
<th style="width: 40%">{%= __("Reference") %}</th>
|
||||||
|
<th style="width: 15%; text-align: right;">{%= __("Debit") %}</th>
|
||||||
|
<th style="width: 15%; text-align: right;">{%= __("Credit") %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for(var i=0, l=data.length; i<l; i++) { %}
|
||||||
|
{% if (data[i].posting_date) { %}
|
||||||
|
<tr>
|
||||||
|
<td>{%= dateutil.str_to_user(data[i].posting_date) %}</td>
|
||||||
|
<td>{%= data[i].journal_voucher %}</td>
|
||||||
|
<td>{%= __("Against") %}: {%= data[i].against_account %}
|
||||||
|
{% if (data[i].reference) { %}
|
||||||
|
<br>{%= __("Reference") %}: {%= data[i].reference %}
|
||||||
|
{% if (data[i].ref_date) { %}
|
||||||
|
<br>{%= __("Reference Date") %}: {%= dateutil.str_to_user(data[i].ref_date) %}
|
||||||
|
{% } %}
|
||||||
|
{% } %}
|
||||||
|
{% if (data[i].clearance_date) { %}
|
||||||
|
<br>{%= __("Clearance Date") %}: {%= dateutil.str_to_user(data[i].clearance_date) %}
|
||||||
|
{% } %}
|
||||||
|
</td>
|
||||||
|
<td style="text-align: right">{%= format_currency(data[i].debit) %}</td>
|
||||||
|
<td style="text-align: right">{%= format_currency(data[i].credit) %}</td>
|
||||||
|
</tr>
|
||||||
|
{% } else { %}
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td>{%= data[i].journal_voucher %}</td>
|
||||||
|
<td style="text-align: right">{%= format_currency(data[i].debit) %}</td>
|
||||||
|
<td style="text-align: right">{%= format_currency(data[i].credit) %}</td>
|
||||||
|
</tr>
|
||||||
|
{% } %}
|
||||||
|
{% } %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p class="text-right text-muted">Printed On {%= dateutil.str_to_user(dateutil.get_datetime_as_string()) %}</p>
|
||||||
@ -19,28 +19,29 @@ def execute(filters=None):
|
|||||||
|
|
||||||
total_debit, total_credit = 0,0
|
total_debit, total_credit = 0,0
|
||||||
for d in data:
|
for d in data:
|
||||||
total_debit += flt(d[4])
|
total_debit += flt(d[2])
|
||||||
total_credit += flt(d[5])
|
total_credit += flt(d[3])
|
||||||
|
|
||||||
bank_bal = flt(balance_as_per_company) - flt(total_debit) + flt(total_credit)
|
bank_bal = flt(balance_as_per_company) - flt(total_debit) + flt(total_credit)
|
||||||
|
|
||||||
data += [
|
data += [
|
||||||
get_balance_row("Balance as per company books", balance_as_per_company),
|
get_balance_row("Balance as per company books", balance_as_per_company),
|
||||||
["", "", "", "Amounts not reflected in bank", total_debit, total_credit],
|
["", "Amounts not reflected in bank", total_debit, total_credit, "", "", "", ""],
|
||||||
get_balance_row("Balance as per bank", bank_bal)
|
get_balance_row("Balance as per bank", bank_bal)
|
||||||
]
|
]
|
||||||
|
|
||||||
return columns, data
|
return columns, data
|
||||||
|
|
||||||
def get_columns():
|
def get_columns():
|
||||||
return ["Journal Voucher:Link/Journal Voucher:140", "Posting Date:Date:100",
|
return ["Posting Date:Date:100", "Journal Voucher:Link/Journal Voucher:200",
|
||||||
"Clearance Date:Date:110", "Against Account:Link/Account:200",
|
"Debit:Currency:120", "Credit:Currency:120",
|
||||||
"Debit:Currency:120", "Credit:Currency:120"
|
"Against Account:Link/Account:200", "Reference::100", "Ref Date:Date:110", "Clearance Date:Date:110"
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_entries(filters):
|
def get_entries(filters):
|
||||||
entries = frappe.db.sql("""select
|
entries = frappe.db.sql("""select
|
||||||
jv.name, jv.posting_date, jv.clearance_date, jvd.against_account, jvd.debit, jvd.credit
|
jv.posting_date, jv.name, jvd.debit, jvd.credit,
|
||||||
|
jvd.against_account, jv.cheque_no, jv.cheque_date, jv.clearance_date
|
||||||
from
|
from
|
||||||
`tabJournal Voucher Detail` jvd, `tabJournal Voucher` jv
|
`tabJournal Voucher Detail` jvd, `tabJournal Voucher` jv
|
||||||
where jvd.parent = jv.name and jv.docstatus=1
|
where jvd.parent = jv.name and jv.docstatus=1
|
||||||
@ -52,6 +53,6 @@ def get_entries(filters):
|
|||||||
|
|
||||||
def get_balance_row(label, amount):
|
def get_balance_row(label, amount):
|
||||||
if amount > 0:
|
if amount > 0:
|
||||||
return ["", "", "", label, amount, 0]
|
return ["", label, amount, 0, "", "", "", ""]
|
||||||
else:
|
else:
|
||||||
return ["", "", "", label, 0, amount]
|
return ["", label, 0, amount, "", "", "", ""]
|
||||||
|
|||||||
53
erpnext/accounts/report/financial_statements.html
Normal file
53
erpnext/accounts/report/financial_statements.html
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
{%
|
||||||
|
if (report.columns.length > 6) {
|
||||||
|
frappe.throw(__("Too many columns. Export the report and print it using a spreadsheet application."));
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.financial-statements-important td {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.financial-statements-blank-row td {
|
||||||
|
height: 37px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<h2 class="text-center">{%= __(report.report_name) %}</h2>
|
||||||
|
<h4 class="text-center">{%= filters.company %}</h3>
|
||||||
|
<h4 class="text-center">{%= filters.fiscal_year %}</h3>
|
||||||
|
<hr>
|
||||||
|
<table class="table table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width: {%= 100 - (report.columns.length - 2) * 15 %}%"></th>
|
||||||
|
{% for(var i=2, l=report.columns.length; i<l; i++) { %}
|
||||||
|
<th class="text-right">{%= report.columns[i].label %}</th>
|
||||||
|
{% } %}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for(var j=0, k=data.length; j<k; j++) { %}
|
||||||
|
{%
|
||||||
|
var row = data[j];
|
||||||
|
var row_class = data[j].parent_account ? "" : "financial-statements-important";
|
||||||
|
row_class += data[j].account_name ? "" : " financial-statements-blank-row";
|
||||||
|
%}
|
||||||
|
<tr class="{%= row_class %}">
|
||||||
|
<td>
|
||||||
|
<span style="padding-left: {%= cint(data[j].indent) * 2 %}em">{%= row.account_name %}</span>
|
||||||
|
</td>
|
||||||
|
{% for(var i=2, l=report.columns.length; i<l; i++) { %}
|
||||||
|
<td class="text-right">
|
||||||
|
{% var fieldname = report.columns[i].field; %}
|
||||||
|
{% if (!is_null(row[fieldname])) { %}
|
||||||
|
{%= format_currency(row[fieldname]) %}
|
||||||
|
{% } %}
|
||||||
|
</td>
|
||||||
|
{% } %}
|
||||||
|
</tr>
|
||||||
|
{% } %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p class="text-right text-muted">Printed On {%= dateutil.str_to_user(dateutil.get_datetime_as_string()) %}</p>
|
||||||
255
erpnext/accounts/report/financial_statements.py
Normal file
255
erpnext/accounts/report/financial_statements.py
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe import _, _dict
|
||||||
|
from frappe.utils import (flt, cint, getdate, get_first_day, get_last_day,
|
||||||
|
add_months, add_days, formatdate)
|
||||||
|
|
||||||
|
def process_filters(filters):
|
||||||
|
filters.depth = cint(filters.depth) or 3
|
||||||
|
if not filters.periodicity:
|
||||||
|
filters.periodicity = "Yearly"
|
||||||
|
|
||||||
|
def get_period_list(fiscal_year, periodicity, from_beginning=False):
|
||||||
|
"""Get a list of dict {"to_date": to_date, "key": key, "label": label}
|
||||||
|
Periodicity can be (Yearly, Quarterly, Monthly)"""
|
||||||
|
|
||||||
|
start_date, end_date = frappe.db.get_value("Fiscal Year", fiscal_year, ["year_start_date", "year_end_date"])
|
||||||
|
start_date = getdate(start_date)
|
||||||
|
end_date = getdate(end_date)
|
||||||
|
|
||||||
|
if periodicity == "Yearly":
|
||||||
|
period_list = [_dict({"to_date": end_date, "key": fiscal_year, "label": fiscal_year})]
|
||||||
|
else:
|
||||||
|
months_to_add = {
|
||||||
|
"Half-yearly": 6,
|
||||||
|
"Quarterly": 3,
|
||||||
|
"Monthly": 1
|
||||||
|
}[periodicity]
|
||||||
|
|
||||||
|
period_list = []
|
||||||
|
|
||||||
|
# start with first day, so as to avoid year to_dates like 2-April if ever they occur
|
||||||
|
to_date = get_first_day(start_date)
|
||||||
|
|
||||||
|
for i in xrange(12 / months_to_add):
|
||||||
|
to_date = add_months(to_date, months_to_add)
|
||||||
|
|
||||||
|
if to_date == get_first_day(to_date):
|
||||||
|
# if to_date is the first day, get the last day of previous month
|
||||||
|
to_date = add_days(to_date, -1)
|
||||||
|
else:
|
||||||
|
# to_date should be the last day of the new to_date's month
|
||||||
|
to_date = get_last_day(to_date)
|
||||||
|
|
||||||
|
if to_date <= end_date:
|
||||||
|
# the normal case
|
||||||
|
period_list.append(_dict({ "to_date": to_date }))
|
||||||
|
|
||||||
|
# if it ends before a full year
|
||||||
|
if to_date == end_date:
|
||||||
|
break
|
||||||
|
|
||||||
|
else:
|
||||||
|
# if a fiscal year ends before a 12 month period
|
||||||
|
period_list.append(_dict({ "to_date": end_date }))
|
||||||
|
break
|
||||||
|
|
||||||
|
# common processing
|
||||||
|
for opts in period_list:
|
||||||
|
key = opts["to_date"].strftime("%b_%Y").lower()
|
||||||
|
label = formatdate(opts["to_date"], "MMM YYYY")
|
||||||
|
opts.update({
|
||||||
|
"key": key.replace(" ", "_").replace("-", "_"),
|
||||||
|
"label": label,
|
||||||
|
"year_start_date": start_date,
|
||||||
|
"year_end_date": end_date
|
||||||
|
})
|
||||||
|
|
||||||
|
if from_beginning:
|
||||||
|
# set start date as None for all fiscal periods, used in case of Balance Sheet
|
||||||
|
opts["from_date"] = None
|
||||||
|
else:
|
||||||
|
opts["from_date"] = start_date
|
||||||
|
|
||||||
|
return period_list
|
||||||
|
|
||||||
|
def get_data(company, root_type, balance_must_be, period_list, depth, ignore_closing_entries=False):
|
||||||
|
accounts = get_accounts(company, root_type)
|
||||||
|
if not accounts:
|
||||||
|
return None
|
||||||
|
|
||||||
|
accounts, accounts_by_name = filter_accounts(accounts, depth)
|
||||||
|
gl_entries_by_account = get_gl_entries(company, root_type, period_list[0]["from_date"], period_list[-1]["to_date"],
|
||||||
|
accounts[0].lft, accounts[0].rgt, ignore_closing_entries=ignore_closing_entries)
|
||||||
|
|
||||||
|
calculate_values(accounts, gl_entries_by_account, period_list)
|
||||||
|
accumulate_values_into_parents(accounts, accounts_by_name, period_list)
|
||||||
|
out = prepare_data(accounts, balance_must_be, period_list)
|
||||||
|
|
||||||
|
if out:
|
||||||
|
add_total_row(out, balance_must_be, period_list)
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
def calculate_values(accounts, gl_entries_by_account, period_list):
|
||||||
|
for d in accounts:
|
||||||
|
for name in ([d.name] + (d.collapsed_children or [])):
|
||||||
|
for entry in gl_entries_by_account.get(name, []):
|
||||||
|
for period in period_list:
|
||||||
|
entry.posting_date = getdate(entry.posting_date)
|
||||||
|
|
||||||
|
# check if posting date is within the period
|
||||||
|
if entry.posting_date <= period.to_date:
|
||||||
|
d[period.key] = d.get(period.key, 0.0) + flt(entry.debit) - flt(entry.credit)
|
||||||
|
|
||||||
|
|
||||||
|
def accumulate_values_into_parents(accounts, accounts_by_name, period_list):
|
||||||
|
"""accumulate children's values in parent accounts"""
|
||||||
|
for d in reversed(accounts):
|
||||||
|
if d.parent_account:
|
||||||
|
for period in period_list:
|
||||||
|
accounts_by_name[d.parent_account][period.key] = accounts_by_name[d.parent_account].get(period.key, 0.0) + \
|
||||||
|
d.get(period.key, 0.0)
|
||||||
|
|
||||||
|
def prepare_data(accounts, balance_must_be, period_list):
|
||||||
|
out = []
|
||||||
|
year_start_date = period_list[0]["year_start_date"].strftime("%Y-%m-%d")
|
||||||
|
year_end_date = period_list[-1]["year_end_date"].strftime("%Y-%m-%d")
|
||||||
|
|
||||||
|
for d in accounts:
|
||||||
|
# add to output
|
||||||
|
has_value = False
|
||||||
|
row = {
|
||||||
|
"account_name": d.account_name,
|
||||||
|
"account": d.name,
|
||||||
|
"parent_account": d.parent_account,
|
||||||
|
"indent": flt(d.indent),
|
||||||
|
"year_start_date": year_start_date,
|
||||||
|
"year_end_date": year_end_date
|
||||||
|
}
|
||||||
|
for period in period_list:
|
||||||
|
if d.get(period.key):
|
||||||
|
# change sign based on Debit or Credit, since calculation is done using (debit - credit)
|
||||||
|
d[period.key] *= (1 if balance_must_be=="Debit" else -1)
|
||||||
|
|
||||||
|
row[period.key] = flt(d.get(period.key, 0.0), 3)
|
||||||
|
|
||||||
|
if abs(row[period.key]) >= 0.005:
|
||||||
|
# ignore zero values
|
||||||
|
has_value = True
|
||||||
|
|
||||||
|
if has_value:
|
||||||
|
out.append(row)
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
def add_total_row(out, balance_must_be, period_list):
|
||||||
|
row = {
|
||||||
|
"account_name": _("Total ({0})").format(balance_must_be),
|
||||||
|
"account": None
|
||||||
|
}
|
||||||
|
for period in period_list:
|
||||||
|
row[period.key] = out[0].get(period.key, 0.0)
|
||||||
|
out[0][period.key] = ""
|
||||||
|
|
||||||
|
out.append(row)
|
||||||
|
|
||||||
|
# blank row after Total
|
||||||
|
out.append({})
|
||||||
|
|
||||||
|
def get_accounts(company, root_type):
|
||||||
|
# root lft, rgt
|
||||||
|
root_account = frappe.db.sql("""select lft, rgt from `tabAccount`
|
||||||
|
where company=%s and root_type=%s order by lft limit 1""",
|
||||||
|
(company, root_type), as_dict=True)
|
||||||
|
|
||||||
|
if not root_account:
|
||||||
|
return None
|
||||||
|
|
||||||
|
lft, rgt = root_account[0].lft, root_account[0].rgt
|
||||||
|
|
||||||
|
accounts = frappe.db.sql("""select * from `tabAccount`
|
||||||
|
where company=%(company)s and lft >= %(lft)s and rgt <= %(rgt)s order by lft""",
|
||||||
|
{ "company": company, "lft": lft, "rgt": rgt }, as_dict=True)
|
||||||
|
|
||||||
|
return accounts
|
||||||
|
|
||||||
|
def filter_accounts(accounts, depth):
|
||||||
|
parent_children_map = {}
|
||||||
|
accounts_by_name = {}
|
||||||
|
for d in accounts:
|
||||||
|
accounts_by_name[d.name] = d
|
||||||
|
parent_children_map.setdefault(d.parent_account or None, []).append(d)
|
||||||
|
|
||||||
|
filtered_accounts = []
|
||||||
|
def add_to_list(parent, level):
|
||||||
|
if level < depth:
|
||||||
|
for child in (parent_children_map.get(parent) or []):
|
||||||
|
child.indent = level
|
||||||
|
filtered_accounts.append(child)
|
||||||
|
add_to_list(child.name, level + 1)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# include all children at level lower than the depth
|
||||||
|
parent_account = accounts_by_name[parent]
|
||||||
|
parent_account["collapsed_children"] = []
|
||||||
|
for d in accounts:
|
||||||
|
if d.lft > parent_account.lft and d.rgt < parent_account.rgt:
|
||||||
|
parent_account["collapsed_children"].append(d.name)
|
||||||
|
|
||||||
|
add_to_list(None, 0)
|
||||||
|
|
||||||
|
return filtered_accounts, accounts_by_name
|
||||||
|
|
||||||
|
def get_gl_entries(company, root_type, from_date, to_date, root_lft, root_rgt, ignore_closing_entries=False):
|
||||||
|
"""Returns a dict like { "account": [gl entries], ... }"""
|
||||||
|
additional_conditions = []
|
||||||
|
|
||||||
|
if ignore_closing_entries:
|
||||||
|
additional_conditions.append("and ifnull(voucher_type, '')!='Period Closing Voucher'")
|
||||||
|
|
||||||
|
if from_date:
|
||||||
|
additional_conditions.append("and posting_date >= %(from_date)s")
|
||||||
|
|
||||||
|
gl_entries = frappe.db.sql("""select * from `tabGL Entry`
|
||||||
|
where company=%(company)s
|
||||||
|
{additional_conditions}
|
||||||
|
and posting_date <= %(to_date)s
|
||||||
|
and account in (select name from `tabAccount`
|
||||||
|
where lft >= %(lft)s and rgt <= %(rgt)s)
|
||||||
|
order by account, posting_date""".format(additional_conditions="\n".join(additional_conditions)),
|
||||||
|
{
|
||||||
|
"company": company,
|
||||||
|
"from_date": from_date,
|
||||||
|
"to_date": to_date,
|
||||||
|
"lft": root_lft,
|
||||||
|
"rgt": root_rgt
|
||||||
|
},
|
||||||
|
as_dict=True)
|
||||||
|
|
||||||
|
gl_entries_by_account = {}
|
||||||
|
for entry in gl_entries:
|
||||||
|
gl_entries_by_account.setdefault(entry.account, []).append(entry)
|
||||||
|
|
||||||
|
return gl_entries_by_account
|
||||||
|
|
||||||
|
def get_columns(period_list):
|
||||||
|
columns = [{
|
||||||
|
"fieldname": "account",
|
||||||
|
"label": _("Account"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Account",
|
||||||
|
"width": 300
|
||||||
|
}]
|
||||||
|
for period in period_list:
|
||||||
|
columns.append({
|
||||||
|
"fieldname": period.key,
|
||||||
|
"label": period.label,
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"width": 150
|
||||||
|
})
|
||||||
|
|
||||||
|
return columns
|
||||||
@ -1,5 +1,13 @@
|
|||||||
|
<div style="margin-bottom: 7px;" class="text-center">
|
||||||
|
{%= frappe.boot.letter_heads[frappe.defaults.get_default("letter_head")] %}
|
||||||
|
</div>
|
||||||
<h2 class="text-center">{%= __("Statement of Account") %}</h2>
|
<h2 class="text-center">{%= __("Statement of Account") %}</h2>
|
||||||
<h4 class="text-center">{%= filters.account || "General Ledger" %}</h3>
|
<h4 class="text-center">{%= filters.account || "General Ledger" %}</h4>
|
||||||
|
<h5 class="text-center">
|
||||||
|
{%= dateutil.str_to_user(filters.from_date) %}
|
||||||
|
{%= __("to") %}
|
||||||
|
{%= dateutil.str_to_user(filters.to_date) %}
|
||||||
|
</h5>
|
||||||
<hr>
|
<hr>
|
||||||
<table class="table table-bordered">
|
<table class="table table-bordered">
|
||||||
<thead>
|
<thead>
|
||||||
@ -19,7 +27,7 @@
|
|||||||
<td>{%= data[i].voucher_type%}
|
<td>{%= data[i].voucher_type%}
|
||||||
<br>{%= data[i].voucher_no %}</td>
|
<br>{%= data[i].voucher_no %}</td>
|
||||||
<td>{%= data[i].account %}
|
<td>{%= data[i].account %}
|
||||||
<br>{%= __("Against") %}: {%= data[i].account %}
|
<br>{%= __("Against") %}: {%= data[i].against_account %}
|
||||||
<br>{%= __("Remarks") %}: {%= data[i].remarks %}</td>
|
<br>{%= __("Remarks") %}: {%= data[i].remarks %}</td>
|
||||||
<td style="text-align: right">{%= format_currency(data[i].debit) %}</td>
|
<td style="text-align: right">{%= format_currency(data[i].debit) %}</td>
|
||||||
<td style="text-align: right">{%= format_currency(data[i].credit) %}</td>
|
<td style="text-align: right">{%= format_currency(data[i].credit) %}</td>
|
||||||
|
|||||||
@ -0,0 +1 @@
|
|||||||
|
{% include "accounts/report/financial_statements.html" %}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||||
|
// License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
frappe.require("assets/erpnext/js/financial_statements.js");
|
||||||
|
|
||||||
|
frappe.query_reports["Profit and Loss Statement"] = erpnext.financial_statements;
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"add_total_row": 0,
|
||||||
|
"apply_user_permissions": 1,
|
||||||
|
"creation": "2014-07-18 11:43:33.173207",
|
||||||
|
"disabled": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Report",
|
||||||
|
"is_standard": "Yes",
|
||||||
|
"modified": "2014-07-18 11:43:33.173207",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Profit and Loss Statement",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"ref_doctype": "GL Entry",
|
||||||
|
"report_name": "Profit and Loss Statement",
|
||||||
|
"report_type": "Script Report"
|
||||||
|
}
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
from frappe.utils import flt
|
||||||
|
from erpnext.accounts.report.financial_statements import (process_filters, get_period_list, get_columns, get_data)
|
||||||
|
|
||||||
|
def execute(filters=None):
|
||||||
|
process_filters(filters)
|
||||||
|
period_list = get_period_list(filters.fiscal_year, filters.periodicity)
|
||||||
|
|
||||||
|
income = get_data(filters.company, "Income", "Credit", period_list, filters.depth, ignore_closing_entries=True)
|
||||||
|
expense = get_data(filters.company, "Expense", "Debit", period_list, filters.depth, ignore_closing_entries=True)
|
||||||
|
net_profit_loss = get_net_profit_loss(income, expense, period_list)
|
||||||
|
|
||||||
|
data = []
|
||||||
|
data.extend(income or [])
|
||||||
|
data.extend(expense or [])
|
||||||
|
if net_profit_loss:
|
||||||
|
data.append(net_profit_loss)
|
||||||
|
|
||||||
|
columns = get_columns(period_list)
|
||||||
|
|
||||||
|
return columns, data
|
||||||
|
|
||||||
|
def get_net_profit_loss(income, expense, period_list):
|
||||||
|
if income and expense:
|
||||||
|
net_profit_loss = {
|
||||||
|
"account_name": _("Net Profit / Loss"),
|
||||||
|
"account": None,
|
||||||
|
"is_profit_loss": True
|
||||||
|
}
|
||||||
|
|
||||||
|
for period in period_list:
|
||||||
|
net_profit_loss[period.key] = flt(income[-2][period.key] - expense[-2][period.key], 3)
|
||||||
|
|
||||||
|
return net_profit_loss
|
||||||
@ -24,6 +24,7 @@ class PurchaseOrder(BuyingController):
|
|||||||
'target_ref_field': 'qty',
|
'target_ref_field': 'qty',
|
||||||
'source_field': 'qty',
|
'source_field': 'qty',
|
||||||
'percent_join_field': 'prevdoc_docname',
|
'percent_join_field': 'prevdoc_docname',
|
||||||
|
'overflow_type': 'order'
|
||||||
}]
|
}]
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
|||||||
@ -69,7 +69,8 @@ cur_frm.cscript.make_address = function() {
|
|||||||
page_length: 5,
|
page_length: 5,
|
||||||
new_doctype: "Address",
|
new_doctype: "Address",
|
||||||
get_query: function() {
|
get_query: function() {
|
||||||
return "select name, address_type, address_line1, address_line2, city, state, country, pincode, fax, email_id, phone, is_primary_address, is_shipping_address from tabAddress where supplier='"+cur_frm.docname+"' and docstatus != 2 order by is_primary_address desc"
|
return "select name, address_type, address_line1, address_line2, city, state, country, pincode, fax, email_id, phone, is_primary_address, is_shipping_address from tabAddress where supplier='" +
|
||||||
|
cur_frm.doc.name.replace("'", "\\'") + "' and docstatus != 2 order by is_primary_address desc"
|
||||||
},
|
},
|
||||||
as_dict: 1,
|
as_dict: 1,
|
||||||
no_results_message: __('No addresses created'),
|
no_results_message: __('No addresses created'),
|
||||||
@ -87,7 +88,8 @@ cur_frm.cscript.make_contact = function() {
|
|||||||
page_length: 5,
|
page_length: 5,
|
||||||
new_doctype: "Contact",
|
new_doctype: "Contact",
|
||||||
get_query: function() {
|
get_query: function() {
|
||||||
return "select name, first_name, last_name, email_id, phone, mobile_no, department, designation, is_primary_contact from tabContact where supplier='"+cur_frm.docname+"' and docstatus != 2 order by is_primary_contact desc"
|
return "select name, first_name, last_name, email_id, phone, mobile_no, department, designation, is_primary_contact from tabContact where supplier='" +
|
||||||
|
cur_frm.doc.name.replace("'", "\\'") + "' and docstatus != 2 order by is_primary_contact desc"
|
||||||
},
|
},
|
||||||
as_dict: 1,
|
as_dict: 1,
|
||||||
no_results_message: __('No contacts created'),
|
no_results_message: __('No contacts created'),
|
||||||
|
|||||||
@ -195,6 +195,18 @@ def get_data():
|
|||||||
"doctype": "Purchase Invoice",
|
"doctype": "Purchase Invoice",
|
||||||
"is_query_report": True
|
"is_query_report": True
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "report",
|
||||||
|
"name": "Balance Sheet",
|
||||||
|
"doctype": "GL Entry",
|
||||||
|
"is_query_report": True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "report",
|
||||||
|
"name": "Profit and Loss Statement",
|
||||||
|
"doctype": "GL Entry",
|
||||||
|
"is_query_report": True
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "page",
|
"type": "page",
|
||||||
"name": "financial-analytics",
|
"name": "financial-analytics",
|
||||||
|
|||||||
@ -150,7 +150,7 @@ def get_data():
|
|||||||
{
|
{
|
||||||
"type": "report",
|
"type": "report",
|
||||||
"is_query_report": True,
|
"is_query_report": True,
|
||||||
"name": "Supplier Addresses And Contacts",
|
"name": "Supplier Addresses and Contacts",
|
||||||
"doctype": "Supplier"
|
"doctype": "Supplier"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -206,7 +206,7 @@ def get_data():
|
|||||||
{
|
{
|
||||||
"type": "report",
|
"type": "report",
|
||||||
"is_query_report": True,
|
"is_query_report": True,
|
||||||
"name": "Customer Addresses And Contacts",
|
"name": "Customer Addresses and Contacts",
|
||||||
"doctype": "Contact"
|
"doctype": "Contact"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -17,6 +17,7 @@ class BuyingController(StockController):
|
|||||||
self.supplier_name = frappe.db.get_value("Supplier",
|
self.supplier_name = frappe.db.get_value("Supplier",
|
||||||
self.supplier, "supplier_name")
|
self.supplier, "supplier_name")
|
||||||
self.is_item_table_empty()
|
self.is_item_table_empty()
|
||||||
|
self.set_qty_as_per_stock_uom()
|
||||||
self.validate_stock_or_nonstock_items()
|
self.validate_stock_or_nonstock_items()
|
||||||
self.validate_warehouse()
|
self.validate_warehouse()
|
||||||
|
|
||||||
@ -317,3 +318,10 @@ class BuyingController(StockController):
|
|||||||
def is_item_table_empty(self):
|
def is_item_table_empty(self):
|
||||||
if not len(self.get(self.fname)):
|
if not len(self.get(self.fname)):
|
||||||
frappe.throw(_("Item table can not be blank"))
|
frappe.throw(_("Item table can not be blank"))
|
||||||
|
|
||||||
|
def set_qty_as_per_stock_uom(self):
|
||||||
|
for d in self.get(self.fname):
|
||||||
|
if d.meta.get_field("stock_qty") and not d.stock_qty:
|
||||||
|
if not d.conversion_factor:
|
||||||
|
frappe.throw(_("Row {0}: Conversion Factor is mandatory"))
|
||||||
|
d.stock_qty = flt(d.qty) * flt(d.conversion_factor)
|
||||||
@ -32,34 +32,46 @@ def employee_query(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
return frappe.db.sql("""select name, employee_name from `tabEmployee`
|
return frappe.db.sql("""select name, employee_name from `tabEmployee`
|
||||||
where status = 'Active'
|
where status = 'Active'
|
||||||
and docstatus < 2
|
and docstatus < 2
|
||||||
and (%(key)s like "%(txt)s"
|
and ({key} like %(txt)s
|
||||||
or employee_name like "%(txt)s")
|
or employee_name like %(txt)s)
|
||||||
%(mcond)s
|
{mcond}
|
||||||
order by
|
order by
|
||||||
if(locate("%(_txt)s", name), locate("%(_txt)s", name), 99999),
|
if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
|
||||||
if(locate("%(_txt)s", employee_name), locate("%(_txt)s", employee_name), 99999),
|
if(locate(%(_txt)s, employee_name), locate(%(_txt)s, employee_name), 99999),
|
||||||
name, employee_name
|
name, employee_name
|
||||||
limit %(start)s, %(page_len)s""" % {'key': searchfield, 'txt': "%%%s%%" % txt,
|
limit %(start)s, %(page_len)s""".format(**{
|
||||||
'_txt': txt.replace("%", ""),
|
'key': searchfield,
|
||||||
'mcond':get_match_cond(doctype), 'start': start, 'page_len': page_len})
|
'mcond': get_match_cond(doctype)
|
||||||
|
}), {
|
||||||
|
'txt': "%%%s%%" % txt,
|
||||||
|
'_txt': txt.replace("%", ""),
|
||||||
|
'start': start,
|
||||||
|
'page_len': page_len
|
||||||
|
})
|
||||||
|
|
||||||
# searches for leads which are not converted
|
# searches for leads which are not converted
|
||||||
def lead_query(doctype, txt, searchfield, start, page_len, filters):
|
def lead_query(doctype, txt, searchfield, start, page_len, filters):
|
||||||
return frappe.db.sql("""select name, lead_name, company_name from `tabLead`
|
return frappe.db.sql("""select name, lead_name, company_name from `tabLead`
|
||||||
where docstatus < 2
|
where docstatus < 2
|
||||||
and ifnull(status, '') != 'Converted'
|
and ifnull(status, '') != 'Converted'
|
||||||
and (%(key)s like "%(txt)s"
|
and ({key} like %(txt)s
|
||||||
or lead_name like "%(txt)s"
|
or lead_name like %(txt)s
|
||||||
or company_name like "%(txt)s")
|
or company_name like %(txt)s)
|
||||||
%(mcond)s
|
{mcond}
|
||||||
order by
|
order by
|
||||||
if(locate("%(_txt)s", name), locate("%(_txt)s", name), 99999),
|
if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
|
||||||
if(locate("%(_txt)s", lead_name), locate("%(_txt)s", lead_name), 99999),
|
if(locate(%(_txt)s, lead_name), locate(%(_txt)s, lead_name), 99999),
|
||||||
if(locate("%(_txt)s", company_name), locate("%(_txt)s", company_name), 99999),
|
if(locate(%(_txt)s, company_name), locate(%(_txt)s, company_name), 99999),
|
||||||
name, lead_name
|
name, lead_name
|
||||||
limit %(start)s, %(page_len)s""" % {'key': searchfield, 'txt': "%%%s%%" % txt,
|
limit %(start)s, %(page_len)s""".format(**{
|
||||||
'_txt': txt.replace("%", ""),
|
'key': searchfield,
|
||||||
'mcond':get_match_cond(doctype), 'start': start, 'page_len': page_len})
|
'mcond':get_match_cond(doctype)
|
||||||
|
}), {
|
||||||
|
'txt': "%%%s%%" % txt,
|
||||||
|
'_txt': txt.replace("%", ""),
|
||||||
|
'start': start,
|
||||||
|
'page_len': page_len
|
||||||
|
})
|
||||||
|
|
||||||
# searches for customer
|
# searches for customer
|
||||||
def customer_query(doctype, txt, searchfield, start, page_len, filters):
|
def customer_query(doctype, txt, searchfield, start, page_len, filters):
|
||||||
@ -72,19 +84,25 @@ def customer_query(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
|
|
||||||
fields = ", ".join(fields)
|
fields = ", ".join(fields)
|
||||||
|
|
||||||
return frappe.db.sql("""select %(field)s from `tabCustomer`
|
return frappe.db.sql("""select {fields} from `tabCustomer`
|
||||||
where docstatus < 2
|
where docstatus < 2
|
||||||
and (%(key)s like "%(txt)s"
|
and ({key} like %(txt)s
|
||||||
or customer_name like "%(txt)s")
|
or customer_name like %(txt)s)
|
||||||
%(mcond)s
|
{mcond}
|
||||||
order by
|
order by
|
||||||
if(locate("%(_txt)s", name), locate("%(_txt)s", name), 99999),
|
if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
|
||||||
if(locate("%(_txt)s", customer_name), locate("%(_txt)s", customer_name), 99999),
|
if(locate(%(_txt)s, customer_name), locate(%(_txt)s, customer_name), 99999),
|
||||||
name, customer_name
|
name, customer_name
|
||||||
limit %(start)s, %(page_len)s""" % {'field': fields,'key': searchfield,
|
limit %(start)s, %(page_len)s""".format(**{
|
||||||
'txt': "%%%s%%" % txt, '_txt': txt.replace("%", ""),
|
"fields": fields,
|
||||||
'mcond':get_match_cond(doctype),
|
"key": searchfield,
|
||||||
'start': start, 'page_len': page_len})
|
"mcond": get_match_cond(doctype)
|
||||||
|
}), {
|
||||||
|
'txt': "%%%s%%" % txt,
|
||||||
|
'_txt': txt.replace("%", ""),
|
||||||
|
'start': start,
|
||||||
|
'page_len': page_len
|
||||||
|
})
|
||||||
|
|
||||||
# searches for supplier
|
# searches for supplier
|
||||||
def supplier_query(doctype, txt, searchfield, start, page_len, filters):
|
def supplier_query(doctype, txt, searchfield, start, page_len, filters):
|
||||||
@ -95,19 +113,25 @@ def supplier_query(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
fields = ["name", "supplier_name", "supplier_type"]
|
fields = ["name", "supplier_name", "supplier_type"]
|
||||||
fields = ", ".join(fields)
|
fields = ", ".join(fields)
|
||||||
|
|
||||||
return frappe.db.sql("""select %(field)s from `tabSupplier`
|
return frappe.db.sql("""select {field} from `tabSupplier`
|
||||||
where docstatus < 2
|
where docstatus < 2
|
||||||
and (%(key)s like "%(txt)s"
|
and ({key} like %(txt)s
|
||||||
or supplier_name like "%(txt)s")
|
or supplier_name like %(txt)s)
|
||||||
%(mcond)s
|
{mcond}
|
||||||
order by
|
order by
|
||||||
if(locate("%(_txt)s", name), locate("%(_txt)s", name), 99999),
|
if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
|
||||||
if(locate("%(_txt)s", supplier_name), locate("%(_txt)s", supplier_name), 99999),
|
if(locate(%(_txt)s, supplier_name), locate(%(_txt)s, supplier_name), 99999),
|
||||||
name, supplier_name
|
name, supplier_name
|
||||||
limit %(start)s, %(page_len)s """ % {'field': fields,'key': searchfield,
|
limit %(start)s, %(page_len)s """.format(**{
|
||||||
'txt': "%%%s%%" % txt, '_txt': txt.replace("%", ""),
|
'field': fields,
|
||||||
'mcond':get_match_cond(doctype), 'start': start,
|
'key': searchfield,
|
||||||
'page_len': page_len})
|
'mcond':get_match_cond(doctype)
|
||||||
|
}), {
|
||||||
|
'txt': "%%%s%%" % txt,
|
||||||
|
'_txt': txt.replace("%", ""),
|
||||||
|
'start': start,
|
||||||
|
'page_len': page_len
|
||||||
|
})
|
||||||
|
|
||||||
def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
|
def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
|
||||||
tax_accounts = frappe.db.sql("""select name, parent_account from tabAccount
|
tax_accounts = frappe.db.sql("""select name, parent_account from tabAccount
|
||||||
@ -143,7 +167,8 @@ def item_query(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
where tabItem.docstatus < 2
|
where tabItem.docstatus < 2
|
||||||
and (tabItem.end_of_life > %(today)s or ifnull(tabItem.end_of_life, '0000-00-00')='0000-00-00')
|
and (tabItem.end_of_life > %(today)s or ifnull(tabItem.end_of_life, '0000-00-00')='0000-00-00')
|
||||||
and (tabItem.`{key}` LIKE %(txt)s
|
and (tabItem.`{key}` LIKE %(txt)s
|
||||||
or tabItem.item_name LIKE %(txt)s)
|
or tabItem.item_name LIKE %(txt)s
|
||||||
|
or tabItem.description LIKE %(txt)s)
|
||||||
{fcond} {mcond}
|
{fcond} {mcond}
|
||||||
order by
|
order by
|
||||||
if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
|
if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
|
||||||
|
|||||||
@ -132,11 +132,12 @@ class StatusUpdater(Document):
|
|||||||
if not item[args['target_ref_field']]:
|
if not item[args['target_ref_field']]:
|
||||||
msgprint(_("Note: System will not check over-delivery and over-booking for Item {0} as quantity or amount is 0").format(item.item_code))
|
msgprint(_("Note: System will not check over-delivery and over-booking for Item {0} as quantity or amount is 0").format(item.item_code))
|
||||||
elif args.get('no_tolerance'):
|
elif args.get('no_tolerance'):
|
||||||
item['reduce_by'] = item[args['target_field']] - \
|
item['reduce_by'] = item[args['target_field']] - item[args['target_ref_field']]
|
||||||
item[args['target_ref_field']]
|
|
||||||
if item['reduce_by'] > .01:
|
if item['reduce_by'] > .01:
|
||||||
msgprint(_("Allowance for over-delivery / over-billing crossed for Item {0}").format(item.item_code))
|
msgprint(_("Allowance for over-{0} crossed for Item {1}")
|
||||||
throw(_("{0} must be less than or equal to {1}").format(_(item.target_ref_field), item[args["target_ref_field"]]))
|
.format(args["overflow_type"], item.item_code))
|
||||||
|
throw(_("{0} must be reduced by {1} or you should increase overflow tolerance")
|
||||||
|
.format(_(item.target_ref_field.title()), item["reduce_by"]))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.check_overflow_with_tolerance(item, args)
|
self.check_overflow_with_tolerance(item, args)
|
||||||
@ -156,8 +157,10 @@ class StatusUpdater(Document):
|
|||||||
item['max_allowed'] = flt(item[args['target_ref_field']] * (100+tolerance)/100)
|
item['max_allowed'] = flt(item[args['target_ref_field']] * (100+tolerance)/100)
|
||||||
item['reduce_by'] = item[args['target_field']] - item['max_allowed']
|
item['reduce_by'] = item[args['target_field']] - item['max_allowed']
|
||||||
|
|
||||||
msgprint(_("Allowance for over-delivery / over-billing crossed for Item {0}.").format(item["item_code"]))
|
msgprint(_("Allowance for over-{0} crossed for Item {1}.")
|
||||||
throw(_("{0} must be less than or equal to {1}").format(item["target_ref_field"].title(), item["max_allowed"]))
|
.format(args["overflow_type"], item["item_code"]))
|
||||||
|
throw(_("{0} must be reduced by {1} or you should increase overflow tolerance")
|
||||||
|
.format(_(item["target_ref_field"].title()), item["reduce_by"]))
|
||||||
|
|
||||||
def update_qty(self, change_modified=True):
|
def update_qty(self, change_modified=True):
|
||||||
"""
|
"""
|
||||||
@ -263,8 +266,7 @@ def get_tolerance_for(item_code, item_tolerance={}, global_tolerance=None):
|
|||||||
|
|
||||||
if not tolerance:
|
if not tolerance:
|
||||||
if global_tolerance == None:
|
if global_tolerance == None:
|
||||||
global_tolerance = flt(frappe.db.get_value('Global Defaults', None,
|
global_tolerance = flt(frappe.db.get_value('Stock Settings', None, 'tolerance'))
|
||||||
'tolerance'))
|
|
||||||
tolerance = global_tolerance
|
tolerance = global_tolerance
|
||||||
|
|
||||||
item_tolerance[item_code] = tolerance
|
item_tolerance[item_code] = tolerance
|
||||||
|
|||||||
@ -240,7 +240,7 @@ class StockController(AccountsController):
|
|||||||
else:
|
else:
|
||||||
is_expense_account = frappe.db.get_value("Account",
|
is_expense_account = frappe.db.get_value("Account",
|
||||||
item.get("expense_account"), "report_type")=="Profit and Loss"
|
item.get("expense_account"), "report_type")=="Profit and Loss"
|
||||||
if self.doctype != "Purchase Receipt" and not is_expense_account:
|
if self.doctype not in ("Purchase Receipt", "Stock Reconciliation") and not is_expense_account:
|
||||||
frappe.throw(_("Expense / Difference account ({0}) must be a 'Profit or Loss' account")
|
frappe.throw(_("Expense / Difference account ({0}) must be a 'Profit or Loss' account")
|
||||||
.format(item.get("expense_account")))
|
.format(item.get("expense_account")))
|
||||||
if is_expense_account and not item.get("cost_center"):
|
if is_expense_account and not item.get("cost_center"):
|
||||||
|
|||||||
@ -7,6 +7,8 @@ app_icon = "icon-th"
|
|||||||
app_color = "#e74c3c"
|
app_color = "#e74c3c"
|
||||||
app_version = __version__
|
app_version = __version__
|
||||||
|
|
||||||
|
error_report_email = "support@erpnext.com"
|
||||||
|
|
||||||
app_include_js = "assets/js/erpnext.min.js"
|
app_include_js = "assets/js/erpnext.min.js"
|
||||||
app_include_css = "assets/css/erpnext.css"
|
app_include_css = "assets/css/erpnext.css"
|
||||||
web_include_js = "assets/js/erpnext-web.min.js"
|
web_include_js = "assets/js/erpnext-web.min.js"
|
||||||
|
|||||||
@ -39,16 +39,16 @@ class ProductionOrder(Document):
|
|||||||
def validate_sales_order(self):
|
def validate_sales_order(self):
|
||||||
if self.sales_order:
|
if self.sales_order:
|
||||||
so = frappe.db.sql("""select name, delivery_date from `tabSales Order`
|
so = frappe.db.sql("""select name, delivery_date from `tabSales Order`
|
||||||
where name=%s and docstatus = 1""", self.sales_order, as_dict=1)[0]
|
where name=%s and docstatus = 1""", self.sales_order, as_dict=1)
|
||||||
|
|
||||||
if not so.name:
|
if len(so):
|
||||||
|
if not self.expected_delivery_date:
|
||||||
|
self.expected_delivery_date = so[0].delivery_date
|
||||||
|
|
||||||
|
self.validate_production_order_against_so()
|
||||||
|
else:
|
||||||
frappe.throw(_("Sales Order {0} is not valid") % self.sales_order)
|
frappe.throw(_("Sales Order {0} is not valid") % self.sales_order)
|
||||||
|
|
||||||
if not self.expected_delivery_date:
|
|
||||||
self.expected_delivery_date = so.delivery_date
|
|
||||||
|
|
||||||
self.validate_production_order_against_so()
|
|
||||||
|
|
||||||
def validate_warehouse(self):
|
def validate_warehouse(self):
|
||||||
from erpnext.stock.utils import validate_warehouse_company
|
from erpnext.stock.utils import validate_warehouse_company
|
||||||
|
|
||||||
|
|||||||
@ -37,8 +37,8 @@ cur_frm.fields_dict['pp_details'].grid.get_field('item_code').get_query = functi
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.fields_dict['pp_details'].grid.get_field('bom_no').get_query = function(doc) {
|
cur_frm.fields_dict['pp_details'].grid.get_field('bom_no').get_query = function(doc, cdt, cdn) {
|
||||||
var d = locals[this.doctype][this.docname];
|
var d = locals[cdt][cdn];
|
||||||
if (d.item_code) {
|
if (d.item_code) {
|
||||||
return {
|
return {
|
||||||
query: "erpnext.controllers.queries.bom",
|
query: "erpnext.controllers.queries.bom",
|
||||||
|
|||||||
@ -67,4 +67,5 @@ erpnext.patches.v4_0.set_naming_series_property_setter
|
|||||||
erpnext.patches.v4_1.set_outgoing_email_footer
|
erpnext.patches.v4_1.set_outgoing_email_footer
|
||||||
erpnext.patches.v4_1.fix_jv_remarks
|
erpnext.patches.v4_1.fix_jv_remarks
|
||||||
erpnext.patches.v4_1.fix_sales_order_delivered_status
|
erpnext.patches.v4_1.fix_sales_order_delivered_status
|
||||||
erpnext.patches.v4_1.fix_delivery_and_billing_status_for_draft_so
|
erpnext.patches.v4_1.fix_delivery_and_billing_status
|
||||||
|
execute:frappe.db.sql("update `tabAccount` set root_type='Liability' where root_type='Income' and report_type='Balance Sheet'")
|
||||||
@ -5,8 +5,8 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
frappe.db.sql("""update `tabSales Order` set delivery_status = 'Not Delivered'
|
frappe.db.sql("""update `tabSales Order` set delivery_status = 'Not Delivered'
|
||||||
where delivery_status = 'Delivered' and ifnull(per_delivered, 0) = 0 and docstatus = 0""")
|
where delivery_status = 'Delivered' and ifnull(per_delivered, 0) = 0 and ifnull(docstatus, 0) in (0, 1)""")
|
||||||
|
|
||||||
frappe.db.sql("""update `tabSales Order` set billing_status = 'Not Billed'
|
frappe.db.sql("""update `tabSales Order` set billing_status = 'Not Billed'
|
||||||
where billing_status = 'Billed' and ifnull(per_billed, 0) = 0 and docstatus = 0""")
|
where billing_status = 'Billed' and ifnull(per_billed, 0) = 0 and ifnull(docstatus, 0) in (0, 1)""")
|
||||||
@ -55,7 +55,7 @@ class Project(Document):
|
|||||||
"event_type": "Private",
|
"event_type": "Private",
|
||||||
"ref_type": self.doctype,
|
"ref_type": self.doctype,
|
||||||
"ref_name": self.name
|
"ref_name": self.name
|
||||||
}).insert()
|
}).insert(ignore_permissions=True)
|
||||||
|
|
||||||
def on_trash(self):
|
def on_trash(self):
|
||||||
delete_events(self.doctype, self.name)
|
delete_events(self.doctype, self.name)
|
||||||
|
|||||||
75
erpnext/public/js/financial_statements.js
Normal file
75
erpnext/public/js/financial_statements.js
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
frappe.provide("erpnext.financial_statements");
|
||||||
|
|
||||||
|
erpnext.financial_statements = {
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"fieldname":"company",
|
||||||
|
"label": __("Company"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Company",
|
||||||
|
"default": frappe.defaults.get_user_default("company"),
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"fiscal_year",
|
||||||
|
"label": __("Fiscal Year"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Fiscal Year",
|
||||||
|
"default": frappe.defaults.get_user_default("fiscal_year"),
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "periodicity",
|
||||||
|
"label": __("Periodicity"),
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"options": "Yearly\nHalf-yearly\nQuarterly\nMonthly",
|
||||||
|
"default": "Yearly",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "depth",
|
||||||
|
"label": __("Depth"),
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"options": "3\n4\n5",
|
||||||
|
"default": "3"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"formatter": function(row, cell, value, columnDef, dataContext) {
|
||||||
|
if (columnDef.df.fieldname=="account") {
|
||||||
|
var link = $("<a></a>")
|
||||||
|
.text(dataContext.account_name)
|
||||||
|
.attr("onclick", "erpnext.financial_statements.open_general_ledger(" + JSON.stringify(dataContext) + ")");
|
||||||
|
|
||||||
|
var span = $("<span></span>")
|
||||||
|
.css("padding-left", (cint(dataContext.indent) * 21) + "px")
|
||||||
|
.append(link);
|
||||||
|
|
||||||
|
value = span.wrap("<p></p>").parent().html();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
value = erpnext.financial_statements.default_formatter(row, cell, value, columnDef, dataContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dataContext.parent_account) {
|
||||||
|
var $value = $(value).css("font-weight", "bold");
|
||||||
|
if (dataContext.is_profit_loss && dataContext[columnDef.df.fieldname] < 0) {
|
||||||
|
$value.addClass("text-danger");
|
||||||
|
}
|
||||||
|
|
||||||
|
value = $value.wrap("<p></p>").parent().html();
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
"open_general_ledger": function(data) {
|
||||||
|
if (!data.account) return;
|
||||||
|
|
||||||
|
frappe.route_options = {
|
||||||
|
"account": data.account,
|
||||||
|
"company": frappe.query_report.filters_by_name.company.get_value(),
|
||||||
|
"from_date": data.year_start_date,
|
||||||
|
"to_date": data.year_end_date
|
||||||
|
};
|
||||||
|
frappe.set_route("query-report", "General Ledger");
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -71,7 +71,7 @@ $.extend(erpnext.queries, {
|
|||||||
|
|
||||||
warehouse: function(doc) {
|
warehouse: function(doc) {
|
||||||
return {
|
return {
|
||||||
filters: [["Warehouse", "company", "in", ["", doc.company]]]
|
filters: [["Warehouse", "company", "in", ["", cstr(doc.company)]]]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -20,16 +20,13 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
|||||||
currency: currency,
|
currency: currency,
|
||||||
price_list_currency: currency,
|
price_list_currency: currency,
|
||||||
status: "Draft",
|
status: "Draft",
|
||||||
fiscal_year: frappe.defaults.get_user_default("fiscal_year"),
|
|
||||||
is_subcontracted: "No",
|
is_subcontracted: "No",
|
||||||
}, function(fieldname, value) {
|
}, function(fieldname, value) {
|
||||||
if(me.frm.fields_dict[fieldname] && !me.frm.doc[fieldname])
|
if(me.frm.fields_dict[fieldname] && !me.frm.doc[fieldname])
|
||||||
me.frm.set_value(fieldname, value);
|
me.frm.set_value(fieldname, value);
|
||||||
});
|
});
|
||||||
|
|
||||||
if(!this.frm.doc.company) {
|
if(this.frm.doc.company) {
|
||||||
this.frm.set_value("company", frappe.defaults.get_user_default("company"));
|
|
||||||
} else {
|
|
||||||
cur_frm.script_manager.trigger("company");
|
cur_frm.script_manager.trigger("company");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -332,7 +329,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
|||||||
method: "erpnext.accounts.doctype.pricing_rule.pricing_rule.apply_pricing_rule",
|
method: "erpnext.accounts.doctype.pricing_rule.pricing_rule.apply_pricing_rule",
|
||||||
args: { args: this._get_args(item) },
|
args: { args: this._get_args(item) },
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if (!r.exc) {
|
if (!r.exc && r.message) {
|
||||||
me._set_values_for_item_list(r.message);
|
me._set_values_for_item_list(r.message);
|
||||||
if(calculate_taxes_and_totals) me.calculate_taxes_and_totals();
|
if(calculate_taxes_and_totals) me.calculate_taxes_and_totals();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -86,7 +86,8 @@ cur_frm.cscript.make_address = function() {
|
|||||||
page_length: 5,
|
page_length: 5,
|
||||||
new_doctype: "Address",
|
new_doctype: "Address",
|
||||||
get_query: function() {
|
get_query: function() {
|
||||||
return "select name, address_type, address_line1, address_line2, city, state, country, pincode, fax, email_id, phone, is_primary_address, is_shipping_address from tabAddress where customer='"+cur_frm.docname+"' and docstatus != 2 order by is_primary_address desc"
|
return "select name, address_type, address_line1, address_line2, city, state, country, pincode, fax, email_id, phone, is_primary_address, is_shipping_address from tabAddress where customer='" +
|
||||||
|
cur_frm.doc.name.replace("'", "\\'") + "' and docstatus != 2 order by is_primary_address desc"
|
||||||
},
|
},
|
||||||
as_dict: 1,
|
as_dict: 1,
|
||||||
no_results_message: __('No addresses created'),
|
no_results_message: __('No addresses created'),
|
||||||
@ -104,7 +105,8 @@ cur_frm.cscript.make_contact = function() {
|
|||||||
page_length: 5,
|
page_length: 5,
|
||||||
new_doctype: "Contact",
|
new_doctype: "Contact",
|
||||||
get_query: function() {
|
get_query: function() {
|
||||||
return "select name, first_name, last_name, email_id, phone, mobile_no, department, designation, is_primary_contact from tabContact where customer='"+cur_frm.docname+"' and docstatus != 2 order by is_primary_contact desc"
|
return "select name, first_name, last_name, email_id, phone, mobile_no, department, designation, is_primary_contact from tabContact where customer='" +
|
||||||
|
cur_frm.doc.name.replace("'", "\\'") + "' and docstatus != 2 order by is_primary_contact desc"
|
||||||
},
|
},
|
||||||
as_dict: 1,
|
as_dict: 1,
|
||||||
no_results_message: __('No contacts created'),
|
no_results_message: __('No contacts created'),
|
||||||
|
|||||||
@ -28,7 +28,8 @@ class InstallationNote(TransactionBase):
|
|||||||
'source_field': 'qty',
|
'source_field': 'qty',
|
||||||
'percent_join_field': 'prevdoc_docname',
|
'percent_join_field': 'prevdoc_docname',
|
||||||
'status_field': 'installation_status',
|
'status_field': 'installation_status',
|
||||||
'keyword': 'Installed'
|
'keyword': 'Installed',
|
||||||
|
'overflow_type': 'installation'
|
||||||
}]
|
}]
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
|||||||
@ -420,7 +420,7 @@
|
|||||||
"label": "Taxes and Charges Calculation",
|
"label": "Taxes and Charges Calculation",
|
||||||
"oldfieldtype": "HTML",
|
"oldfieldtype": "HTML",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 0
|
"print_hide": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "section_break_43",
|
"fieldname": "section_break_43",
|
||||||
@ -883,7 +883,7 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"modified": "2014-07-07 17:47:40.089520",
|
"modified": "2014-07-10 02:43:45.504009",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Sales Order",
|
"name": "Sales Order",
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
{
|
{
|
||||||
"apply_user_permissions": 1,
|
"apply_user_permissions": 1,
|
||||||
"creation": "2012-10-04 18:45:27",
|
"creation": "2012-10-04 18:45:27",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "Report",
|
"doctype": "Report",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"is_standard": "Yes",
|
"is_standard": "Yes",
|
||||||
"modified": "2014-06-03 07:18:17.006732",
|
"modified": "2014-07-14 07:18:17.006732",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Customer Addresses And Contacts",
|
"name": "Customer Addresses and Contacts",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"query": "SELECT\n\t`tabCustomer`.name as customer_id,\n\t`tabCustomer`.customer_name,\n\t`tabCustomer`.customer_group,\n\t`tabAddress`.address_line1,\n\t`tabAddress`.address_line2,\n\t`tabAddress`.city,\n\t`tabAddress`.state,\n\t`tabAddress`.pincode,\n\t`tabAddress`.country,\n\t`tabAddress`.is_primary_address, \n\t`tabContact`.first_name,\n\t`tabContact`.last_name,\n\t`tabContact`.phone,\n\t`tabContact`.mobile_no,\n\t`tabContact`.email_id,\n\t`tabContact`.is_primary_contact\nFROM\n\t`tabCustomer`\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.customer=`tabCustomer`.name\n\t)\n\tleft join `tabContact` on (\n\t\t`tabContact`.customer=`tabCustomer`.name\n\t)\nWHERE\n\t`tabCustomer`.docstatus<2\nORDER BY\n\t`tabCustomer`.name asc",
|
"query": "SELECT\n\t`tabCustomer`.name as customer_id,\n\t`tabCustomer`.customer_name,\n\t`tabCustomer`.customer_group,\n\t`tabAddress`.address_line1,\n\t`tabAddress`.address_line2,\n\t`tabAddress`.city,\n\t`tabAddress`.state,\n\t`tabAddress`.pincode,\n\t`tabAddress`.country,\n\t`tabAddress`.is_primary_address, \n\t`tabContact`.first_name,\n\t`tabContact`.last_name,\n\t`tabContact`.phone,\n\t`tabContact`.mobile_no,\n\t`tabContact`.email_id,\n\t`tabContact`.is_primary_contact\nFROM\n\t`tabCustomer`\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.customer=`tabCustomer`.name\n\t)\n\tleft join `tabContact` on (\n\t\t`tabContact`.customer=`tabCustomer`.name\n\t)\nWHERE\n\t`tabCustomer`.docstatus<2\nORDER BY\n\t`tabCustomer`.name asc",
|
||||||
"ref_doctype": "Customer",
|
"ref_doctype": "Customer",
|
||||||
"report_name": "Customer Addresses And Contacts",
|
"report_name": "Customer Addresses And Contacts",
|
||||||
"report_type": "Query Report"
|
"report_type": "Query Report"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,6 +53,15 @@
|
|||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"reqd": 0
|
"reqd": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "country",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Country",
|
||||||
|
"options": "Country",
|
||||||
|
"permlevel": 0,
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "charts_section",
|
"fieldname": "charts_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
@ -60,18 +69,10 @@
|
|||||||
"label": "Chart of Accounts",
|
"label": "Chart of Accounts",
|
||||||
"permlevel": 0
|
"permlevel": 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "country",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Country",
|
|
||||||
"options": "Country",
|
|
||||||
"permlevel": 0,
|
|
||||||
"reqd": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "chart_of_accounts",
|
"fieldname": "chart_of_accounts",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 1,
|
"ignore_user_permissions": 1,
|
||||||
"label": "Chart of Accounts",
|
"label": "Chart of Accounts",
|
||||||
"options": "Chart of Accounts",
|
"options": "Chart of Accounts",
|
||||||
@ -348,7 +349,7 @@
|
|||||||
],
|
],
|
||||||
"icon": "icon-building",
|
"icon": "icon-building",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"modified": "2014-05-27 03:49:08.597191",
|
"modified": "2014-07-17 19:30:24.487672",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Setup",
|
"module": "Setup",
|
||||||
"name": "Company",
|
"name": "Company",
|
||||||
|
|||||||
@ -241,7 +241,7 @@ class Company(Document):
|
|||||||
[_('Sales'),_('Direct Income'),'Ledger','Income Account','Profit and Loss', None, 'Income'],
|
[_('Sales'),_('Direct Income'),'Ledger','Income Account','Profit and Loss', None, 'Income'],
|
||||||
[_('Service'),_('Direct Income'),'Ledger','Income Account','Profit and Loss', None, 'Income'],
|
[_('Service'),_('Direct Income'),'Ledger','Income Account','Profit and Loss', None, 'Income'],
|
||||||
[_('Indirect Income'),_('Income'),'Group','Income Account','Profit and Loss', None, 'Income'],
|
[_('Indirect Income'),_('Income'),'Group','Income Account','Profit and Loss', None, 'Income'],
|
||||||
[_('Source of Funds (Liabilities)'), None,'Group', None,'Balance Sheet', None, 'Income'],
|
[_('Source of Funds (Liabilities)'), None,'Group', None,'Balance Sheet', None, 'Liability'],
|
||||||
[_('Capital Account'),_('Source of Funds (Liabilities)'),'Group', None,'Balance Sheet', None, 'Liability'],
|
[_('Capital Account'),_('Source of Funds (Liabilities)'),'Group', None,'Balance Sheet', None, 'Liability'],
|
||||||
[_('Reserves and Surplus'),_('Capital Account'),'Ledger', None,'Balance Sheet', None, 'Liability'],
|
[_('Reserves and Surplus'),_('Capital Account'),'Ledger', None,'Balance Sheet', None, 'Liability'],
|
||||||
[_('Shareholders Funds'),_('Capital Account'),'Ledger', None,'Balance Sheet', None, 'Liability'],
|
[_('Shareholders Funds'),_('Capital Account'),'Ledger', None,'Balance Sheet', None, 'Liability'],
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
def install(company):
|
def install(company):
|
||||||
docs = [
|
docs = [
|
||||||
@ -27,44 +28,45 @@ def install(company):
|
|||||||
'group_or_ledger': 2,
|
'group_or_ledger': 2,
|
||||||
'account_type': 3,
|
'account_type': 3,
|
||||||
'report_type': 4,
|
'report_type': 4,
|
||||||
'tax_rate': 5
|
'tax_rate': 5,
|
||||||
|
'root_type': 6
|
||||||
}
|
}
|
||||||
|
|
||||||
acc_list_india = [
|
acc_list_india = [
|
||||||
['CENVAT Capital Goods','Tax Assets','Ledger','Chargeable','Balance Sheet', None],
|
[_('CENVAT Capital Goods'),_(_('Tax Assets')),'Ledger','Chargeable','Balance Sheet', None, 'Asset'],
|
||||||
['CENVAT','Tax Assets','Ledger','Chargeable','Balance Sheet', None],
|
[_('CENVAT'),_('Tax Assets'),'Ledger','Chargeable','Balance Sheet', None, 'Asset'],
|
||||||
['CENVAT Service Tax','Tax Assets','Ledger','Chargeable','Balance Sheet', None],
|
[_('CENVAT Service Tax'),_('Tax Assets'),'Ledger','Chargeable','Balance Sheet', None, 'Asset'],
|
||||||
['CENVAT Service Tax Cess 1','Tax Assets','Ledger','Chargeable','Balance Sheet', None],
|
[_('CENVAT Service Tax Cess 1'),_('Tax Assets'),'Ledger','Chargeable','Balance Sheet', None, 'Asset'],
|
||||||
['CENVAT Service Tax Cess 2','Tax Assets','Ledger','Chargeable','Balance Sheet', None],
|
[_('CENVAT Service Tax Cess 2'),_('Tax Assets'),'Ledger','Chargeable','Balance Sheet', None, 'Asset'],
|
||||||
['CENVAT Edu Cess','Tax Assets','Ledger','Chargeable','Balance Sheet', None],
|
[_('CENVAT Edu Cess'),_('Tax Assets'),'Ledger','Chargeable','Balance Sheet', None, 'Asset'],
|
||||||
['CENVAT SHE Cess','Tax Assets','Ledger','Chargeable','Balance Sheet', None],
|
[_('CENVAT SHE Cess'),_('Tax Assets'),'Ledger','Chargeable','Balance Sheet', None, 'Asset'],
|
||||||
['Excise Duty 4','Tax Assets','Ledger','Tax','Balance Sheet','4.00'],
|
[_('Excise Duty 4'),_('Tax Assets'),'Ledger','Tax','Balance Sheet','4.00', 'Asset'],
|
||||||
['Excise Duty 8','Tax Assets','Ledger','Tax','Balance Sheet','8.00'],
|
[_('Excise Duty 8'),_('Tax Assets'),'Ledger','Tax','Balance Sheet','8.00', 'Asset'],
|
||||||
['Excise Duty 10','Tax Assets','Ledger','Tax','Balance Sheet','10.00'],
|
[_('Excise Duty 10'),_('Tax Assets'),'Ledger','Tax','Balance Sheet','10.00', 'Asset'],
|
||||||
['Excise Duty 14','Tax Assets','Ledger','Tax','Balance Sheet','14.00'],
|
[_('Excise Duty 14'),_('Tax Assets'),'Ledger','Tax','Balance Sheet','14.00', 'Asset'],
|
||||||
['Excise Duty Edu Cess 2','Tax Assets','Ledger','Tax','Balance Sheet','2.00'],
|
[_('Excise Duty Edu Cess 2'),_('Tax Assets'),'Ledger','Tax','Balance Sheet','2.00', 'Asset'],
|
||||||
['Excise Duty SHE Cess 1','Tax Assets','Ledger','Tax','Balance Sheet','1.00'],
|
[_('Excise Duty SHE Cess 1'),_('Tax Assets'),'Ledger','Tax','Balance Sheet','1.00', 'Asset'],
|
||||||
['P L A','Tax Assets','Ledger','Chargeable','Balance Sheet', None],
|
[_('P L A'),_('Tax Assets'),'Ledger','Chargeable','Balance Sheet', None, 'Asset'],
|
||||||
['P L A - Cess Portion','Tax Assets','Ledger','Chargeable','Balance Sheet', None],
|
[_('P L A - Cess Portion'),_('Tax Assets'),'Ledger','Chargeable','Balance Sheet', None, 'Asset'],
|
||||||
['Edu. Cess on Excise','Duties and Taxes','Ledger','Tax','Balance Sheet','2.00'],
|
[_('Edu. Cess on Excise'),_('Duties and Taxes'),'Ledger','Tax','Balance Sheet','2.00', 'Liability'],
|
||||||
['Edu. Cess on Service Tax','Duties and Taxes','Ledger','Tax','Balance Sheet','2.00'],
|
[_('Edu. Cess on Service Tax'),_('Duties and Taxes'),'Ledger','Tax','Balance Sheet','2.00', 'Liability'],
|
||||||
['Edu. Cess on TDS','Duties and Taxes','Ledger','Tax','Balance Sheet','2.00'],
|
[_('Edu. Cess on TDS'),_('Duties and Taxes'),'Ledger','Tax','Balance Sheet','2.00', 'Liability'],
|
||||||
['Excise Duty @ 4','Duties and Taxes','Ledger','Tax','Balance Sheet','4.00'],
|
[_('Excise Duty @ 4'),_('Duties and Taxes'),'Ledger','Tax','Balance Sheet','4.00', 'Liability'],
|
||||||
['Excise Duty @ 8','Duties and Taxes','Ledger','Tax','Balance Sheet','8.00'],
|
[_('Excise Duty @ 8'),_('Duties and Taxes'),'Ledger','Tax','Balance Sheet','8.00', 'Liability'],
|
||||||
['Excise Duty @ 10','Duties and Taxes','Ledger','Tax','Balance Sheet','10.00'],
|
[_('Excise Duty @ 10'),_('Duties and Taxes'),'Ledger','Tax','Balance Sheet','10.00', 'Liability'],
|
||||||
['Excise Duty @ 14','Duties and Taxes','Ledger','Tax','Balance Sheet','14.00'],
|
[_('Excise Duty @ 14'),_('Duties and Taxes'),'Ledger','Tax','Balance Sheet','14.00', 'Liability'],
|
||||||
['Service Tax','Duties and Taxes','Ledger','Tax','Balance Sheet','10.3'],
|
[_('Service Tax'),_('Duties and Taxes'),'Ledger','Tax','Balance Sheet','10.3', 'Liability'],
|
||||||
['SHE Cess on Excise','Duties and Taxes','Ledger','Tax','Balance Sheet','1.00'],
|
[_('SHE Cess on Excise'),_('Duties and Taxes'),'Ledger','Tax','Balance Sheet','1.00', 'Liability'],
|
||||||
['SHE Cess on Service Tax','Duties and Taxes','Ledger','Tax','Balance Sheet','1.00'],
|
[_('SHE Cess on Service Tax'),_('Duties and Taxes'),'Ledger','Tax','Balance Sheet','1.00', 'Liability'],
|
||||||
['SHE Cess on TDS','Duties and Taxes','Ledger','Tax','Balance Sheet','1.00'],
|
[_('SHE Cess on TDS'),_('Duties and Taxes'),'Ledger','Tax','Balance Sheet','1.00', 'Liability'],
|
||||||
['Professional Tax','Duties and Taxes','Ledger','Chargeable','Balance Sheet', None],
|
[_('Professional Tax'),_('Duties and Taxes'),'Ledger','Chargeable','Balance Sheet', None, 'Liability'],
|
||||||
['VAT','Duties and Taxes','Ledger','Chargeable','Balance Sheet', None],
|
[_('VAT'),_('Duties and Taxes'),'Ledger','Chargeable','Balance Sheet', None, 'Liability'],
|
||||||
['TDS (Advertisement)','Duties and Taxes','Ledger','Chargeable','Balance Sheet', None],
|
[_('TDS (Advertisement)'),_('Duties and Taxes'),'Ledger','Chargeable','Balance Sheet', None, 'Liability'],
|
||||||
['TDS (Commission)','Duties and Taxes','Ledger','Chargeable','Balance Sheet', None],
|
[_('TDS (Commission)'),_('Duties and Taxes'),'Ledger','Chargeable','Balance Sheet', None, 'Liability'],
|
||||||
['TDS (Contractor)','Duties and Taxes','Ledger','Chargeable','Balance Sheet', None],
|
[_('TDS (Contractor)'),_('Duties and Taxes'),'Ledger','Chargeable','Balance Sheet', None, 'Liability'],
|
||||||
['TDS (Interest)','Duties and Taxes','Ledger','Chargeable','Balance Sheet', None],
|
[_('TDS (Interest)'),_('Duties and Taxes'),'Ledger','Chargeable','Balance Sheet', None, 'Liability'],
|
||||||
['TDS (Rent)','Duties and Taxes','Ledger','Chargeable','Balance Sheet', None],
|
[_('TDS (Rent)'),_('Duties and Taxes'),'Ledger','Chargeable','Balance Sheet', None, 'Liability'],
|
||||||
['TDS (Salary)','Duties and Taxes','Ledger','Chargeable','Balance Sheet', None]
|
[_('TDS (Salary)'),_('Duties and Taxes'),'Ledger','Chargeable','Balance Sheet', None, 'Liability']
|
||||||
]
|
]
|
||||||
|
|
||||||
for lst in acc_list_india:
|
for lst in acc_list_india:
|
||||||
|
|||||||
@ -82,7 +82,7 @@ def get_child_groups(item_group_name):
|
|||||||
def get_item_for_list_in_html(context):
|
def get_item_for_list_in_html(context):
|
||||||
# add missing absolute link in files
|
# add missing absolute link in files
|
||||||
# user may forget it during upload
|
# user may forget it during upload
|
||||||
if context.get("website_image", "").startswith("files/"):
|
if (context.get("website_image") or "").startswith("files/"):
|
||||||
context["website_image"] = "/" + context["website_image"]
|
context["website_image"] = "/" + context["website_image"]
|
||||||
return frappe.get_template("templates/includes/product_in_grid.html").render(context)
|
return frappe.get_template("templates/includes/product_in_grid.html").render(context)
|
||||||
|
|
||||||
|
|||||||
@ -41,7 +41,8 @@ cur_frm.cscript.make_address = function() {
|
|||||||
frappe.set_route("Form", "Address", address.name);
|
frappe.set_route("Form", "Address", address.name);
|
||||||
},
|
},
|
||||||
get_query: function() {
|
get_query: function() {
|
||||||
return "select name, address_type, address_line1, address_line2, city, state, country, pincode, fax, email_id, phone, is_primary_address, is_shipping_address from tabAddress where sales_partner='"+cur_frm.docname+"' and docstatus != 2 order by is_primary_address desc"
|
return "select name, address_type, address_line1, address_line2, city, state, country, pincode, fax, email_id, phone, is_primary_address, is_shipping_address from tabAddress where sales_partner='" +
|
||||||
|
cur_frm.doc.name.replace("'", "\\'") + "' and docstatus != 2 order by is_primary_address desc"
|
||||||
},
|
},
|
||||||
as_dict: 1,
|
as_dict: 1,
|
||||||
no_results_message: __('No addresses created'),
|
no_results_message: __('No addresses created'),
|
||||||
@ -64,7 +65,8 @@ cur_frm.cscript.make_contact = function() {
|
|||||||
frappe.set_route("Form", "Contact", contact.name);
|
frappe.set_route("Form", "Contact", contact.name);
|
||||||
},
|
},
|
||||||
get_query: function() {
|
get_query: function() {
|
||||||
return "select name, first_name, last_name, email_id, phone, mobile_no, department, designation, is_primary_contact from tabContact where sales_partner='"+cur_frm.docname+"' and docstatus != 2 order by is_primary_contact desc"
|
return "select name, first_name, last_name, email_id, phone, mobile_no, department, designation, is_primary_contact from tabContact where sales_partner='" +
|
||||||
|
cur_frm.doc.name.replace("'", "\\'") + "' and docstatus != 2 order by is_primary_contact desc"
|
||||||
},
|
},
|
||||||
as_dict: 1,
|
as_dict: 1,
|
||||||
no_results_message: __('No contacts created'),
|
no_results_message: __('No contacts created'),
|
||||||
|
|||||||
@ -113,9 +113,11 @@ def update_user_name(args):
|
|||||||
last_name=%(last_name)s WHERE name=%(name)s""", args)
|
last_name=%(last_name)s WHERE name=%(name)s""", args)
|
||||||
|
|
||||||
if args.get("attach_user"):
|
if args.get("attach_user"):
|
||||||
filename, filetype, content = args.get("attach_user").split(",")
|
attach_user = args.get("attach_user").split(",")
|
||||||
fileurl = save_file(filename, content, "User", args.get("name"), decode=True).file_url
|
if len(attach_user)==3:
|
||||||
frappe.db.set_value("User", args.get("name"), "user_image", fileurl)
|
filename, filetype, content = attach_user
|
||||||
|
fileurl = save_file(filename, content, "User", args.get("name"), decode=True).file_url
|
||||||
|
frappe.db.set_value("User", args.get("name"), "user_image", fileurl)
|
||||||
|
|
||||||
add_all_roles_to(args.get("name"))
|
add_all_roles_to(args.get("name"))
|
||||||
|
|
||||||
@ -319,9 +321,11 @@ def create_items(args):
|
|||||||
}).insert()
|
}).insert()
|
||||||
|
|
||||||
if args.get("item_img_" + str(i)):
|
if args.get("item_img_" + str(i)):
|
||||||
filename, filetype, content = args.get("item_img_" + str(i)).split(",")
|
item_image = args.get("item_img_" + str(i)).split(",")
|
||||||
fileurl = save_file(filename, content, "Item", item, decode=True).file_url
|
if len(item_image)==3:
|
||||||
frappe.db.set_value("Item", item, "image", fileurl)
|
filename, filetype, content = item_image
|
||||||
|
fileurl = save_file(filename, content, "Item", item, decode=True).file_url
|
||||||
|
frappe.db.set_value("Item", item, "image", fileurl)
|
||||||
|
|
||||||
def create_customers(args):
|
def create_customers(args):
|
||||||
for i in xrange(1,6):
|
for i in xrange(1,6):
|
||||||
@ -374,17 +378,21 @@ def create_letter_head(args):
|
|||||||
"is_default": 1
|
"is_default": 1
|
||||||
}).insert()
|
}).insert()
|
||||||
|
|
||||||
filename, filetype, content = args.get("attach_letterhead").split(",")
|
attach_letterhead = args.get("attach_letterhead").split(",")
|
||||||
fileurl = save_file(filename, content, "Letter Head", _("Standard"), decode=True).file_url
|
if len(attach_letterhead)==3:
|
||||||
frappe.db.set_value("Letter Head", _("Standard"), "content", "<img src='%s' style='max-width: 100%%;'>" % fileurl)
|
filename, filetype, content = attach_letterhead
|
||||||
|
fileurl = save_file(filename, content, "Letter Head", _("Standard"), decode=True).file_url
|
||||||
|
frappe.db.set_value("Letter Head", _("Standard"), "content", "<img src='%s' style='max-width: 100%%;'>" % fileurl)
|
||||||
|
|
||||||
def create_logo(args):
|
def create_logo(args):
|
||||||
if args.get("attach_logo"):
|
if args.get("attach_logo"):
|
||||||
filename, filetype, content = args.get("attach_logo").split(",")
|
attach_logo = args.get("attach_logo").split(",")
|
||||||
fileurl = save_file(filename, content, "Website Settings", "Website Settings",
|
if len(attach_logo)==3:
|
||||||
decode=True).file_url
|
filename, filetype, content = attach_logo
|
||||||
frappe.db.set_value("Website Settings", "Website Settings", "banner_html",
|
fileurl = save_file(filename, content, "Website Settings", "Website Settings",
|
||||||
"<img src='%s' style='max-width: 100%%;'>" % fileurl)
|
decode=True).file_url
|
||||||
|
frappe.db.set_value("Website Settings", "Website Settings", "banner_html",
|
||||||
|
"<img src='%s' style='max-width: 100%%;'>" % fileurl)
|
||||||
|
|
||||||
def add_all_roles_to(name):
|
def add_all_roles_to(name):
|
||||||
user = frappe.get_doc("User", name)
|
user = frappe.get_doc("User", name)
|
||||||
|
|||||||
@ -427,6 +427,7 @@
|
|||||||
"label": "Taxes and Charges Calculation",
|
"label": "Taxes and Charges Calculation",
|
||||||
"oldfieldtype": "HTML",
|
"oldfieldtype": "HTML",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
|
"print_hide": 1,
|
||||||
"read_only": 0
|
"read_only": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1008,7 +1009,7 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"in_create": 0,
|
"in_create": 0,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"modified": "2014-06-23 07:55:47.859869",
|
"modified": "2014-07-10 02:45:47.673011",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Delivery Note",
|
"name": "Delivery Note",
|
||||||
|
|||||||
@ -29,7 +29,8 @@ class DeliveryNote(SellingController):
|
|||||||
'source_field': 'qty',
|
'source_field': 'qty',
|
||||||
'percent_join_field': 'against_sales_order',
|
'percent_join_field': 'against_sales_order',
|
||||||
'status_field': 'delivery_status',
|
'status_field': 'delivery_status',
|
||||||
'keyword': 'Delivered'
|
'keyword': 'Delivered',
|
||||||
|
'overflow_type': 'delivery'
|
||||||
}]
|
}]
|
||||||
|
|
||||||
def onload(self):
|
def onload(self):
|
||||||
|
|||||||
@ -11,8 +11,7 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten
|
|||||||
this._super();
|
this._super();
|
||||||
this.frm.set_query("item_code", this.frm.cscript.fname, function() {
|
this.frm.set_query("item_code", this.frm.cscript.fname, function() {
|
||||||
return {
|
return {
|
||||||
query: "erpnext.controllers.queries.item_query",
|
query: "erpnext.controllers.queries.item_query"
|
||||||
filters: {'is_stock_item': 'Yes'}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@ -27,6 +27,7 @@ class PurchaseReceipt(BuyingController):
|
|||||||
'target_ref_field': 'qty',
|
'target_ref_field': 'qty',
|
||||||
'source_field': 'qty',
|
'source_field': 'qty',
|
||||||
'percent_join_field': 'prevdoc_docname',
|
'percent_join_field': 'prevdoc_docname',
|
||||||
|
'overflow_type': 'receipt'
|
||||||
}]
|
}]
|
||||||
|
|
||||||
def onload(self):
|
def onload(self):
|
||||||
|
|||||||
@ -92,7 +92,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
|||||||
set_default_account: function() {
|
set_default_account: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
|
|
||||||
if(cint(frappe.defaults.get_default("auto_accounting_for_stock"))) {
|
if(cint(frappe.defaults.get_default("auto_accounting_for_stock")) && this.frm.doc.company) {
|
||||||
var account_for = "stock_adjustment_account";
|
var account_for = "stock_adjustment_account";
|
||||||
|
|
||||||
if (this.frm.doc.purpose == "Purchase Return")
|
if (this.frm.doc.purpose == "Purchase Return")
|
||||||
@ -230,6 +230,36 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
|||||||
if(!row.t_warehouse) row.t_warehouse = this.frm.doc.to_warehouse;
|
if(!row.t_warehouse) row.t_warehouse = this.frm.doc.to_warehouse;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
source_mandatory: ["Material Issue", "Material Transfer", "Purchase Return"],
|
||||||
|
target_mandatory: ["Material Receipt", "Material Transfer", "Sales Return"],
|
||||||
|
|
||||||
|
from_warehouse: function(doc) {
|
||||||
|
var me = this;
|
||||||
|
this.set_warehouse_if_missing("s_warehouse", doc.from_warehouse, function(row) {
|
||||||
|
return me.source_mandatory.indexOf(me.frm.doc.purpose)!==-1;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
to_warehouse: function(doc) {
|
||||||
|
var me = this;
|
||||||
|
this.set_warehouse_if_missing("t_warehouse", doc.to_warehouse, function(row) {
|
||||||
|
return me.target_mandatory.indexOf(me.frm.doc.purpose)!==-1;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
set_warehouse_if_missing: function(fieldname, value, condition) {
|
||||||
|
for (var i=0, l=(this.frm.doc.mtn_details || []).length; i<l; i++) {
|
||||||
|
var row = this.frm.doc.mtn_details[i];
|
||||||
|
if (!row[fieldname]) {
|
||||||
|
if (condition && !condition(row)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
frappe.model.set_value(row.doctype, row.name, fieldname, value, "Link");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
mtn_details_on_form_rendered: function(doc, grid_row) {
|
mtn_details_on_form_rendered: function(doc, grid_row) {
|
||||||
erpnext.setup_serial_no(grid_row)
|
erpnext.setup_serial_no(grid_row)
|
||||||
},
|
},
|
||||||
|
|||||||
@ -204,7 +204,7 @@ class StockEntry(StockController):
|
|||||||
if not self.posting_date or not self.posting_time:
|
if not self.posting_date or not self.posting_time:
|
||||||
frappe.throw(_("Posting date and posting time is mandatory"))
|
frappe.throw(_("Posting date and posting time is mandatory"))
|
||||||
|
|
||||||
allow_negative_stock = frappe.db.get_value("Stock Settings", None, "allow_negative_stock")
|
allow_negative_stock = cint(frappe.db.get_default("allow_negative_stock"))
|
||||||
|
|
||||||
for d in self.get('mtn_details'):
|
for d in self.get('mtn_details'):
|
||||||
args = frappe._dict({
|
args = frappe._dict({
|
||||||
@ -219,7 +219,8 @@ class StockEntry(StockController):
|
|||||||
# get actual stock at source warehouse
|
# get actual stock at source warehouse
|
||||||
d.actual_qty = get_previous_sle(args).get("qty_after_transaction") or 0
|
d.actual_qty = get_previous_sle(args).get("qty_after_transaction") or 0
|
||||||
|
|
||||||
if d.s_warehouse and not allow_negative_stock and d.actual_qty <= d.transfer_qty:
|
# validate qty during submit
|
||||||
|
if d.docstatus==1 and d.s_warehouse and not allow_negative_stock and d.actual_qty < d.transfer_qty:
|
||||||
frappe.throw(_("""Row {0}: Qty not avalable in warehouse {1} on {2} {3}.
|
frappe.throw(_("""Row {0}: Qty not avalable in warehouse {1} on {2} {3}.
|
||||||
Available Qty: {4}, Transfer Qty: {5}""").format(d.idx, d.s_warehouse,
|
Available Qty: {4}, Transfer Qty: {5}""").format(d.idx, d.s_warehouse,
|
||||||
self.posting_date, self.posting_time, d.actual_qty, d.transfer_qty))
|
self.posting_date, self.posting_time, d.actual_qty, d.transfer_qty))
|
||||||
@ -675,9 +676,9 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
|
|
||||||
batch_nos = None
|
batch_nos = None
|
||||||
args = {
|
args = {
|
||||||
'item_code': filters['item_code'],
|
'item_code': filters.get("item_code"),
|
||||||
's_warehouse': filters['s_warehouse'],
|
's_warehouse': filters.get('s_warehouse'),
|
||||||
'posting_date': filters['posting_date'],
|
'posting_date': filters.get('posting_date'),
|
||||||
'txt': "%%%s%%" % txt,
|
'txt': "%%%s%%" % txt,
|
||||||
'mcond':get_match_cond(doctype),
|
'mcond':get_match_cond(doctype),
|
||||||
"start": start,
|
"start": start,
|
||||||
|
|||||||
@ -21,7 +21,7 @@ class TestStockEntry(unittest.TestCase):
|
|||||||
frappe.db.sql("""delete from `tabMaterial Request`""")
|
frappe.db.sql("""delete from `tabMaterial Request`""")
|
||||||
self._clear_stock_account_balance()
|
self._clear_stock_account_balance()
|
||||||
|
|
||||||
frappe.db.set_value("Stock Settings", None, "auto_indent", True)
|
frappe.db.set_value("Stock Settings", None, "auto_indent", 1)
|
||||||
|
|
||||||
st1 = frappe.copy_doc(test_records[0])
|
st1 = frappe.copy_doc(test_records[0])
|
||||||
st1.insert()
|
st1.insert()
|
||||||
@ -664,15 +664,17 @@ class TestStockEntry(unittest.TestCase):
|
|||||||
def test_serial_no_not_exists(self):
|
def test_serial_no_not_exists(self):
|
||||||
self._clear_stock_account_balance()
|
self._clear_stock_account_balance()
|
||||||
frappe.db.sql("delete from `tabSerial No` where name in ('ABCD', 'EFGH')")
|
frappe.db.sql("delete from `tabSerial No` where name in ('ABCD', 'EFGH')")
|
||||||
|
make_serialized_item(target_warehouse="_Test Warehouse 1 - _TC")
|
||||||
se = frappe.copy_doc(test_records[0])
|
se = frappe.copy_doc(test_records[0])
|
||||||
se.purpose = "Material Issue"
|
se.purpose = "Material Issue"
|
||||||
se.get("mtn_details")[0].item_code = "_Test Serialized Item"
|
se.get("mtn_details")[0].item_code = "_Test Serialized Item With Series"
|
||||||
se.get("mtn_details")[0].qty = 2
|
se.get("mtn_details")[0].qty = 2
|
||||||
se.get("mtn_details")[0].s_warehouse = "_Test Warehouse 1 - _TC"
|
se.get("mtn_details")[0].s_warehouse = "_Test Warehouse 1 - _TC"
|
||||||
se.get("mtn_details")[0].t_warehouse = None
|
se.get("mtn_details")[0].t_warehouse = None
|
||||||
se.get("mtn_details")[0].serial_no = "ABCD\nEFGH"
|
se.get("mtn_details")[0].serial_no = "ABCD\nEFGH"
|
||||||
se.get("mtn_details")[0].transfer_qty = 2
|
se.get("mtn_details")[0].transfer_qty = 2
|
||||||
se.insert()
|
se.insert()
|
||||||
|
|
||||||
self.assertRaises(SerialNoNotExistsError, se.submit)
|
self.assertRaises(SerialNoNotExistsError, se.submit)
|
||||||
|
|
||||||
def test_serial_duplicate(self):
|
def test_serial_duplicate(self):
|
||||||
@ -699,8 +701,8 @@ class TestStockEntry(unittest.TestCase):
|
|||||||
return se, serial_nos
|
return se, serial_nos
|
||||||
|
|
||||||
def test_serial_item_error(self):
|
def test_serial_item_error(self):
|
||||||
self._clear_stock_account_balance()
|
|
||||||
se, serial_nos = self.test_serial_by_series()
|
se, serial_nos = self.test_serial_by_series()
|
||||||
|
make_serialized_item("_Test Serialized Item", "ABCD\nEFGH")
|
||||||
|
|
||||||
se = frappe.copy_doc(test_records[0])
|
se = frappe.copy_doc(test_records[0])
|
||||||
se.purpose = "Material Transfer"
|
se.purpose = "Material Transfer"
|
||||||
@ -735,6 +737,8 @@ class TestStockEntry(unittest.TestCase):
|
|||||||
|
|
||||||
def test_serial_warehouse_error(self):
|
def test_serial_warehouse_error(self):
|
||||||
self._clear_stock_account_balance()
|
self._clear_stock_account_balance()
|
||||||
|
make_serialized_item(target_warehouse="_Test Warehouse 1 - _TC")
|
||||||
|
|
||||||
t = make_serialized_item()
|
t = make_serialized_item()
|
||||||
serial_nos = get_serial_nos(t.get("mtn_details")[0].serial_no)
|
serial_nos = get_serial_nos(t.get("mtn_details")[0].serial_no)
|
||||||
|
|
||||||
@ -818,11 +822,16 @@ class TestStockEntry(unittest.TestCase):
|
|||||||
self.assertRaises (StockFreezeError, se.submit)
|
self.assertRaises (StockFreezeError, se.submit)
|
||||||
frappe.db.set_value("Stock Settings", None, "stock_frozen_upto_days", 0)
|
frappe.db.set_value("Stock Settings", None, "stock_frozen_upto_days", 0)
|
||||||
|
|
||||||
def make_serialized_item():
|
def make_serialized_item(item_code=None, serial_no=None, target_warehouse=None):
|
||||||
se = frappe.copy_doc(test_records[0])
|
se = frappe.copy_doc(test_records[0])
|
||||||
se.get("mtn_details")[0].item_code = "_Test Serialized Item With Series"
|
se.get("mtn_details")[0].item_code = item_code or "_Test Serialized Item With Series"
|
||||||
|
se.get("mtn_details")[0].serial_no = serial_no
|
||||||
se.get("mtn_details")[0].qty = 2
|
se.get("mtn_details")[0].qty = 2
|
||||||
se.get("mtn_details")[0].transfer_qty = 2
|
se.get("mtn_details")[0].transfer_qty = 2
|
||||||
|
|
||||||
|
if target_warehouse:
|
||||||
|
se.get("mtn_details")[0].t_warehouse = target_warehouse
|
||||||
|
|
||||||
se.insert()
|
se.insert()
|
||||||
se.submit()
|
se.submit()
|
||||||
return se
|
return se
|
||||||
|
|||||||
@ -152,6 +152,7 @@ def get_basic_details(args, item_doc):
|
|||||||
"min_order_qty": flt(item.min_order_qty) if args.parenttype == "Material Request" else "",
|
"min_order_qty": flt(item.min_order_qty) if args.parenttype == "Material Request" else "",
|
||||||
"conversion_factor": 1.0,
|
"conversion_factor": 1.0,
|
||||||
"qty": 1.0,
|
"qty": 1.0,
|
||||||
|
"stock_qty": 1.0,
|
||||||
"price_list_rate": 0.0,
|
"price_list_rate": 0.0,
|
||||||
"base_price_list_rate": 0.0,
|
"base_price_list_rate": 0.0,
|
||||||
"rate": 0.0,
|
"rate": 0.0,
|
||||||
|
|||||||
@ -176,7 +176,6 @@ def get_buying_amount(voucher_type, voucher_no, item_row, stock_ledger_entries):
|
|||||||
|
|
||||||
def reorder_item():
|
def reorder_item():
|
||||||
""" Reorder item if stock reaches reorder level"""
|
""" Reorder item if stock reaches reorder level"""
|
||||||
|
|
||||||
# if initial setup not completed, return
|
# if initial setup not completed, return
|
||||||
if not frappe.db.sql("select name from `tabFiscal Year` limit 1"):
|
if not frappe.db.sql("select name from `tabFiscal Year` limit 1"):
|
||||||
return
|
return
|
||||||
@ -185,46 +184,69 @@ def reorder_item():
|
|||||||
frappe.local.auto_indent = cint(frappe.db.get_value('Stock Settings', None, 'auto_indent'))
|
frappe.local.auto_indent = cint(frappe.db.get_value('Stock Settings', None, 'auto_indent'))
|
||||||
|
|
||||||
if frappe.local.auto_indent:
|
if frappe.local.auto_indent:
|
||||||
material_requests = {}
|
_reorder_item()
|
||||||
bin_list = frappe.db.sql("""select item_code, warehouse, projected_qty
|
|
||||||
from tabBin where ifnull(item_code, '') != '' and ifnull(warehouse, '') != ''
|
|
||||||
and exists (select name from `tabItem`
|
|
||||||
where `tabItem`.name = `tabBin`.item_code and
|
|
||||||
is_stock_item='Yes' and (is_purchase_item='Yes' or is_sub_contracted_item='Yes') and
|
|
||||||
(ifnull(end_of_life, '0000-00-00')='0000-00-00' or end_of_life > curdate()))""",
|
|
||||||
as_dict=True)
|
|
||||||
|
|
||||||
for bin in bin_list:
|
def _reorder_item():
|
||||||
#check if re-order is required
|
# {"Purchase": {"Company": [{"item_code": "", "warehouse": "", "reorder_qty": 0.0}]}, "Transfer": {...}}
|
||||||
item_reorder = frappe.db.get("Item Reorder",
|
material_requests = {"Purchase": {}, "Transfer": {}}
|
||||||
{"parent": bin.item_code, "warehouse": bin.warehouse})
|
|
||||||
if item_reorder:
|
|
||||||
reorder_level = item_reorder.warehouse_reorder_level
|
|
||||||
reorder_qty = item_reorder.warehouse_reorder_qty
|
|
||||||
material_request_type = item_reorder.material_request_type or "Purchase"
|
|
||||||
else:
|
|
||||||
reorder_level, reorder_qty = frappe.db.get_value("Item", bin.item_code,
|
|
||||||
["re_order_level", "re_order_qty"])
|
|
||||||
material_request_type = "Purchase"
|
|
||||||
|
|
||||||
if flt(reorder_level) and flt(bin.projected_qty) < flt(reorder_level):
|
item_warehouse_projected_qty = get_item_warehouse_projected_qty()
|
||||||
if flt(reorder_level) - flt(bin.projected_qty) > flt(reorder_qty):
|
warehouse_company = frappe._dict(frappe.db.sql("""select name, company from `tabWarehouse`"""))
|
||||||
reorder_qty = flt(reorder_level) - flt(bin.projected_qty)
|
default_company = (frappe.defaults.get_defaults().get("company") or
|
||||||
|
frappe.db.sql("""select name from tabCompany limit 1""")[0][0])
|
||||||
|
|
||||||
company = frappe.db.get_value("Warehouse", bin.warehouse, "company") or \
|
def add_to_material_request(item_code, warehouse, reorder_level, reorder_qty, material_request_type):
|
||||||
frappe.defaults.get_defaults()["company"] or \
|
if warehouse not in item_warehouse_projected_qty[item_code]:
|
||||||
frappe.db.sql("""select name from tabCompany limit 1""")[0][0]
|
# likely a disabled warehouse or a warehouse where BIN does not exist
|
||||||
|
return
|
||||||
|
|
||||||
material_requests.setdefault(material_request_type, frappe._dict()).setdefault(
|
reorder_level = flt(reorder_level)
|
||||||
company, []).append(frappe._dict({
|
reorder_qty = flt(reorder_qty)
|
||||||
"item_code": bin.item_code,
|
projected_qty = item_warehouse_projected_qty[item_code][warehouse]
|
||||||
"warehouse": bin.warehouse,
|
|
||||||
"reorder_qty": reorder_qty
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
if material_requests:
|
if reorder_level and projected_qty < reorder_level:
|
||||||
create_material_request(material_requests)
|
deficiency = reorder_level - projected_qty
|
||||||
|
if deficiency > reorder_qty:
|
||||||
|
reorder_qty = deficiency
|
||||||
|
|
||||||
|
company = warehouse_company.get(warehouse) or default_company
|
||||||
|
|
||||||
|
material_requests[material_request_type].setdefault(company, []).append({
|
||||||
|
"item_code": item_code,
|
||||||
|
"warehouse": warehouse,
|
||||||
|
"reorder_qty": reorder_qty
|
||||||
|
})
|
||||||
|
|
||||||
|
for item_code in item_warehouse_projected_qty:
|
||||||
|
item = frappe.get_doc("Item", item_code)
|
||||||
|
if item.get("item_reorder"):
|
||||||
|
for d in item.get("item_reorder"):
|
||||||
|
add_to_material_request(item_code, d.warehouse, d.warehouse_reorder_level,
|
||||||
|
d.warehouse_reorder_qty, d.material_request_type)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# raise for default warehouse
|
||||||
|
add_to_material_request(item_code, item.default_warehouse, item.re_order_level, item.re_order_qty, "Purchase")
|
||||||
|
|
||||||
|
if material_requests:
|
||||||
|
create_material_request(material_requests)
|
||||||
|
|
||||||
|
def get_item_warehouse_projected_qty():
|
||||||
|
item_warehouse_projected_qty = {}
|
||||||
|
|
||||||
|
for item_code, warehouse, projected_qty in frappe.db.sql("""select item_code, warehouse, projected_qty
|
||||||
|
from tabBin where ifnull(item_code, '') != '' and ifnull(warehouse, '') != ''
|
||||||
|
and exists (select name from `tabItem`
|
||||||
|
where `tabItem`.name = `tabBin`.item_code and
|
||||||
|
is_stock_item='Yes' and (is_purchase_item='Yes' or is_sub_contracted_item='Yes') and
|
||||||
|
(ifnull(end_of_life, '0000-00-00')='0000-00-00' or end_of_life > %s))
|
||||||
|
and exists (select name from `tabWarehouse`
|
||||||
|
where `tabWarehouse`.name = `tabBin`.warehouse
|
||||||
|
and ifnull(disabled, 0)=0)""", nowdate()):
|
||||||
|
|
||||||
|
item_warehouse_projected_qty.setdefault(item_code, {})[warehouse] = flt(projected_qty)
|
||||||
|
|
||||||
|
return item_warehouse_projected_qty
|
||||||
|
|
||||||
def create_material_request(material_requests):
|
def create_material_request(material_requests):
|
||||||
""" Create indent on reaching reorder level """
|
""" Create indent on reaching reorder level """
|
||||||
@ -263,6 +285,7 @@ def create_material_request(material_requests):
|
|||||||
})
|
})
|
||||||
|
|
||||||
for d in items:
|
for d in items:
|
||||||
|
d = frappe._dict(d)
|
||||||
item = frappe.get_doc("Item", d.item_code)
|
item = frappe.get_doc("Item", d.item_code)
|
||||||
mr.append("indent_details", {
|
mr.append("indent_details", {
|
||||||
"doctype": "Material Request Item",
|
"doctype": "Material Request Item",
|
||||||
|
|||||||
@ -8,31 +8,31 @@ from erpnext.utilities.transaction_base import TransactionBase
|
|||||||
from frappe.utils import now, extract_email_id
|
from frappe.utils import now, extract_email_id
|
||||||
|
|
||||||
class SupportTicket(TransactionBase):
|
class SupportTicket(TransactionBase):
|
||||||
|
|
||||||
def get_sender(self, comm):
|
def get_sender(self, comm):
|
||||||
return frappe.db.get_value('Support Email Settings',None,'support_email')
|
return frappe.db.get_value('Support Email Settings',None,'support_email')
|
||||||
|
|
||||||
def get_subject(self, comm):
|
def get_subject(self, comm):
|
||||||
return '[' + self.name + '] ' + (comm.subject or 'No Subject Specified')
|
return '[' + self.name + '] ' + (comm.subject or 'No Subject Specified')
|
||||||
|
|
||||||
def get_content(self, comm):
|
def get_content(self, comm):
|
||||||
signature = frappe.db.get_value('Support Email Settings',None,'support_signature')
|
signature = frappe.db.get_value('Support Email Settings',None,'support_signature')
|
||||||
content = comm.content
|
content = comm.content
|
||||||
if signature:
|
if signature:
|
||||||
content += '<p>' + signature + '</p>'
|
content += '<p>' + signature + '</p>'
|
||||||
return content
|
return content
|
||||||
|
|
||||||
def get_portal_page(self):
|
def get_portal_page(self):
|
||||||
return "ticket"
|
return "ticket"
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.update_status()
|
self.update_status()
|
||||||
self.set_lead_contact(self.raised_by)
|
self.set_lead_contact(self.raised_by)
|
||||||
|
|
||||||
if self.status == "Closed":
|
if self.status == "Closed":
|
||||||
from frappe.widgets.form.assign_to import clear
|
from frappe.widgets.form.assign_to import clear
|
||||||
clear(self.doctype, self.name)
|
clear(self.doctype, self.name)
|
||||||
|
|
||||||
def set_lead_contact(self, email_id):
|
def set_lead_contact(self, email_id):
|
||||||
import email.utils
|
import email.utils
|
||||||
email_id = email.utils.parseaddr(email_id)
|
email_id = email.utils.parseaddr(email_id)
|
||||||
@ -41,8 +41,8 @@ class SupportTicket(TransactionBase):
|
|||||||
self.lead = frappe.db.get_value("Lead", {"email_id": email_id})
|
self.lead = frappe.db.get_value("Lead", {"email_id": email_id})
|
||||||
if not self.contact:
|
if not self.contact:
|
||||||
self.contact = frappe.db.get_value("Contact", {"email_id": email_id})
|
self.contact = frappe.db.get_value("Contact", {"email_id": email_id})
|
||||||
|
|
||||||
if not self.company:
|
if not self.company:
|
||||||
self.company = frappe.db.get_value("Lead", self.lead, "company") or \
|
self.company = frappe.db.get_value("Lead", self.lead, "company") or \
|
||||||
frappe.db.get_default("company")
|
frappe.db.get_default("company")
|
||||||
|
|
||||||
@ -53,15 +53,16 @@ class SupportTicket(TransactionBase):
|
|||||||
if self.status=="Closed" and status !="Closed":
|
if self.status=="Closed" and status !="Closed":
|
||||||
self.resolution_date = now()
|
self.resolution_date = now()
|
||||||
if self.status=="Open" and status !="Open":
|
if self.status=="Open" and status !="Open":
|
||||||
self.resolution_date = ""
|
# if no date, it should be set as None and not a blank string "", as per mysql strict config
|
||||||
|
self.resolution_date = None
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def set_status(name, status):
|
def set_status(name, status):
|
||||||
st = frappe.get_doc("Support Ticket", name)
|
st = frappe.get_doc("Support Ticket", name)
|
||||||
st.status = status
|
st.status = status
|
||||||
st.save()
|
st.save()
|
||||||
|
|
||||||
def auto_close_tickets():
|
def auto_close_tickets():
|
||||||
frappe.db.sql("""update `tabSupport Ticket` set status = 'Closed'
|
frappe.db.sql("""update `tabSupport Ticket` set status = 'Closed'
|
||||||
where status = 'Replied'
|
where status = 'Replied'
|
||||||
and date_sub(curdate(),interval 15 Day) > modified""")
|
and date_sub(curdate(),interval 15 Day) > modified""")
|
||||||
|
|||||||
@ -12,7 +12,8 @@
|
|||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Title",
|
"label": "Title",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1
|
"print_hide": 1,
|
||||||
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Help: To link to another record in the system, use \"#Form/Note/[Note Name]\" as the Link URL. (don't use \"http://\")",
|
"description": "Help: To link to another record in the system, use \"#Form/Note/[Note Name]\" as the Link URL. (don't use \"http://\")",
|
||||||
@ -48,7 +49,7 @@
|
|||||||
],
|
],
|
||||||
"icon": "icon-file-text",
|
"icon": "icon-file-text",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"modified": "2014-05-27 03:49:13.934698",
|
"modified": "2014-07-09 12:54:11.897597",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Utilities",
|
"module": "Utilities",
|
||||||
"name": "Note",
|
"name": "Note",
|
||||||
|
|||||||
@ -190,3 +190,22 @@ def set_stock_balance_as_per_serial_no(item_code=None, posting_date=None, postin
|
|||||||
"posting_date": posting_date,
|
"posting_date": posting_date,
|
||||||
"posting_time": posting_time
|
"posting_time": posting_time
|
||||||
})
|
})
|
||||||
|
|
||||||
|
def reset_serial_no_status_and_warehouse(serial_nos=None):
|
||||||
|
if not serial_nos:
|
||||||
|
serial_nos = frappe.db.sql_list("""select name from `tabSerial No` where status != 'Not in Use'
|
||||||
|
and docstatus = 0""")
|
||||||
|
for serial_no in serial_nos:
|
||||||
|
try:
|
||||||
|
sr = frappe.get_doc("Serial No", serial_no)
|
||||||
|
last_sle = sr.get_last_sle()
|
||||||
|
if flt(last_sle.actual_qty) > 0:
|
||||||
|
sr.warehouse = last_sle.warehouse
|
||||||
|
|
||||||
|
sr.via_stock_ledger = True
|
||||||
|
sr.save()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
frappe.db.sql("""update `tabSerial No` set warehouse='' where status in ('Delivered', 'Purchase Returned')""")
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user