diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py
index 47e3195d71a..de3ee958975 100644
--- a/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/accounts/doctype/sales_invoice/sales_invoice.py
@@ -8,7 +8,7 @@
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
@@ -25,6 +25,8 @@ from webnotes.model.bean import getlist
from webnotes.model.code import get_obj
from webnotes import _, msgprint
+from stock.utils import get_buying_amount, get_sales_bom
+
session = webnotes.session
month_map = {'Monthly': 1, 'Quarterly': 3, 'Half-yearly': 6, 'Yearly': 12}
@@ -95,7 +97,8 @@ class DocType(SellingController):
if not self.doc.recurring_id:
get_obj('Authorization Control').validate_approving_authority(self.doc.doctype,
self.doc.company, self.doc.grand_total, self)
-
+
+ self.set_buying_amount()
self.check_prev_docstatus()
get_obj("Sales Common").update_prevdoc_detail(1,self)
@@ -126,7 +129,7 @@ class DocType(SellingController):
self.check_next_docstatus()
sales_com_obj.update_prevdoc_detail(0, self)
- self.make_gl_entries(is_cancel=1)
+ self.make_gl_entries()
def on_update_after_submit(self):
self.validate_recurring_invoice()
@@ -537,8 +540,7 @@ class DocType(SellingController):
if not w:
ps = webnotes.conn.sql("select name, warehouse from `tabPOS Setting` where ifnull(user,'') = '' and company = '%s'" % self.doc.company)
if not ps:
- msgprint("To make POS entry, please create POS Setting from Accounts --> POS Setting page and refresh the system.")
- raise Exception
+ msgprint("To make POS entry, please create POS Setting from Accounts --> POS Setting page and refresh the system.", raise_exception=True)
elif not ps[0][1]:
msgprint("Please enter warehouse in POS Setting")
else:
@@ -619,8 +621,7 @@ class DocType(SellingController):
'is_cancelled' : (update_stock==1) and 'No' or 'Yes',
'batch_no' : cstr(d['batch_no']),
'serial_no' : d['serial_no']
- })
-
+ })
def update_stock_ledger(self, update_stock):
self.values = []
@@ -648,14 +649,29 @@ class DocType(SellingController):
return ret
- def make_gl_entries(self, is_cancel=0):
- from accounts.general_ledger import make_gl_entries
- gl_entries = []
- auto_inventory_accounting = webnotes.conn.get_value("Global Defaults", None,
- "automatic_inventory_accounting")
- abbr = self.get_company_abbr()
+ def make_gl_entries(self):
+ from accounts.general_ledger import make_gl_entries, merge_similar_entries
- # parent's gl entry
+ gl_entries = []
+
+ self.make_customer_gl_entry(gl_entries)
+
+ self.make_tax_gl_entries(gl_entries)
+
+ self.make_item_gl_entries(gl_entries)
+
+ # merge gl entries before adding pos entries
+ gl_entries = merge_similar_entries(gl_entries)
+
+ self.make_pos_gl_entries(gl_entries)
+
+ update_outstanding = cint(self.doc.is_pos) and self.doc.write_off_account and 'No' or 'Yes'
+
+ if gl_entries:
+ make_gl_entries(gl_entries, cancel=(self.doc.docstatus == 2),
+ update_outstanding=update_outstanding, merge_entries=False)
+
+ def make_customer_gl_entry(self, gl_entries):
if self.doc.grand_total:
gl_entries.append(
self.get_gl_dict({
@@ -665,10 +681,10 @@ class DocType(SellingController):
"remarks": self.doc.remarks,
"against_voucher": self.doc.name,
"against_voucher_type": self.doc.doctype,
- }, is_cancel)
+ })
)
-
- # tax table gl entries
+
+ def make_tax_gl_entries(self, gl_entries):
for tax in self.doclist.get({"parentfield": "other_charges"}):
if flt(tax.tax_amount):
gl_entries.append(
@@ -678,11 +694,21 @@ class DocType(SellingController):
"credit": flt(tax.tax_amount),
"remarks": self.doc.remarks,
"cost_center": tax.cost_center_other_charges
- }, is_cancel)
+ })
)
-
+
+ def make_item_gl_entries(self, gl_entries):
# item gl entries
- for item in getlist(self.doclist, 'entries'):
+ auto_inventory_accounting = \
+ cint(webnotes.defaults.get_global_default("auto_inventory_accounting"))
+
+ if auto_inventory_accounting:
+ if cint(self.doc.is_pos) and cint(self.doc.update_stock):
+ stock_account = self.get_stock_in_hand_account()
+ else:
+ stock_account = "Stock Delivered But Not Billed - %s" % (self.company_abbr,)
+
+ for item in self.doclist.get({"parentfield": "entries"}):
# income account gl entries
if flt(item.amount):
gl_entries.append(
@@ -692,35 +718,33 @@ class DocType(SellingController):
"credit": item.amount,
"remarks": self.doc.remarks,
"cost_center": item.cost_center
- }, is_cancel)
+ })
)
- # if auto inventory accounting enabled and stock item,
- # then do stock related gl entries
- if auto_inventory_accounting and item.delivery_note and \
- webnotes.conn.get_value("Item", item.item_code, "is_stock_item")=="Yes":
- # to-do
- purchase_rate = webnotes.conn.get_value("Delivery Note Item",
- item.dn_detail, "purchase_rate")
- valuation_amount = purchase_rate * item.qty
- # expense account gl entries
- if flt(valuation_amount):
- gl_entries.append(
- self.get_gl_dict({
- "account": item.expense_account,
- "against": "Stock Delivered But Not Billed - %s" % (abbr,),
- "debit": valuation_amount,
- "remarks": self.doc.remarks or "Accounting Entry for Stock"
- }, is_cancel)
- )
- gl_entries.append(
- self.get_gl_dict({
- "account": "Stock Delivered But Not Billed - %s" % (abbr,),
- "against": item.expense_account,
- "credit": valuation_amount,
- "remarks": self.doc.remarks or "Accounting Entry for Stock"
- }, is_cancel)
- )
- if self.doc.is_pos and self.doc.cash_bank_account and self.doc.paid_amount:
+
+ # expense account gl entries
+ if auto_inventory_accounting and flt(item.buying_amount):
+ self.check_expense_account(item)
+
+ gl_entries.append(
+ self.get_gl_dict({
+ "account": item.expense_account,
+ "against": stock_account,
+ "debit": item.buying_amount,
+ "remarks": self.doc.remarks or "Accounting Entry for Stock",
+ "cost_center": item.cost_center
+ })
+ )
+ gl_entries.append(
+ self.get_gl_dict({
+ "account": stock_account,
+ "against": item.expense_account,
+ "credit": item.buying_amount,
+ "remarks": self.doc.remarks or "Accounting Entry for Stock"
+ })
+ )
+
+ def make_pos_gl_entries(self, gl_entries):
+ if cint(self.doc.is_pos) and self.doc.cash_bank_account and self.doc.paid_amount:
# POS, make payment entries
gl_entries.append(
self.get_gl_dict({
@@ -730,7 +754,7 @@ class DocType(SellingController):
"remarks": self.doc.remarks,
"against_voucher": self.doc.name,
"against_voucher_type": self.doc.doctype,
- }, is_cancel)
+ })
)
gl_entries.append(
self.get_gl_dict({
@@ -738,7 +762,7 @@ class DocType(SellingController):
"against": self.doc.debit_to,
"debit": self.doc.paid_amount,
"remarks": self.doc.remarks,
- }, is_cancel)
+ })
)
# write off entries, applicable if only pos
if self.doc.write_off_account and self.doc.write_off_amount:
@@ -750,7 +774,7 @@ class DocType(SellingController):
"remarks": self.doc.remarks,
"against_voucher": self.doc.name,
"against_voucher_type": self.doc.doctype,
- }, is_cancel)
+ })
)
gl_entries.append(
self.get_gl_dict({
@@ -759,23 +783,50 @@ class DocType(SellingController):
"debit": self.doc.write_off_amount,
"remarks": self.doc.remarks,
"cost_center": self.doc.write_off_cost_center
- }, is_cancel)
+ })
)
+
+ def set_buying_amount(self):
+ if cint(self.doc.is_pos) and cint(self.doc.update_stock):
+ stock_ledger_entries = self.get_stock_ledger_entries()
+ item_sales_bom = get_sales_bom()
+ else:
+ stock_ledger_entries = item_sales_bom = None
+
+ for item in self.doclist.get({"parentfield": "entries"}):
+ if item.item_code in self.stock_items:
+ item.buying_amount = self.get_item_buying_amount(item, stock_ledger_entries,
+ item_sales_bom)
+ webnotes.conn.set_value("Sales Invoice Item", item.name,
+ "buying_amount", item.buying_amount)
+
+ def get_item_buying_amount(self, item, stock_ledger_entries, item_sales_bom):
+ item_buying_amount = 0
+ if stock_ledger_entries:
+ # is pos and update stock
+ item_buying_amount = get_buying_amount(item.item_code, item.warehouse, item.qty,
+ self.doc.doctype, self.doc.name, item.name, stock_ledger_entries, item_sales_bom)
+ elif item.delivery_note and item.dn_detail:
+ # against delivery note
+ dn_item = webnotes.conn.get_value("Delivery Note Item", item.dn_detail,
+ ["buying_amount", "qty"], as_dict=1)
+ item_buying_rate = flt(dn_item.buying_amount) / flt(dn_item.qty)
+ item_buying_amount = item_buying_rate * flt(item.qty)
+ return item_buying_amount
- update_outstanding = self.doc.is_pos and self.doc.write_off_account and 'No' or 'Yes'
- merge_entries=cint(self.doc.is_pos)!=1 and 1 or 0
- if gl_entries:
- make_gl_entries(gl_entries, cancel=is_cancel,
- update_outstanding=update_outstanding, merge_entries=merge_entries)
-
+ def check_expense_account(self, item):
+ if not item.expense_account:
+ msgprint(_("""Expense account is mandatory for item: """) + item.item_code,
+ raise_exception=1)
+
def update_c_form(self):
"""Update amended id in C-form"""
if self.doc.c_form_no and self.doc.amended_from:
webnotes.conn.sql("""update `tabC-Form Invoice Detail` set invoice_no = %s,
- invoice_date = %s, territory = %s, net_total = %s,
- grand_total = %s where invoice_no = %s and parent = %s""", (self.doc.name, self.doc.amended_from, self.doc.c_form_no))
-
+ invoice_date = %s, territory = %s, net_total = %s,
+ grand_total = %s where invoice_no = %s and parent = %s""",
+ (self.doc.name, self.doc.amended_from, self.doc.c_form_no))
def check_next_docstatus(self):
submit_jv = webnotes.conn.sql("select t1.name from `tabJournal Voucher` t1,`tabJournal Voucher Detail` t2 where t1.name = t2.parent and t2.against_invoice = '%s' and t1.docstatus = 1" % (self.doc.name))
diff --git a/accounts/doctype/sales_invoice/test_sales_invoice.py b/accounts/doctype/sales_invoice/test_sales_invoice.py
index fb290d27e3a..84eddea2187 100644
--- a/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -38,72 +38,382 @@ class TestSalesInvoice(unittest.TestCase):
si.insert()
si.submit()
- self.assertEquals(webnotes.conn.get_value("Time Log Batch", "_T-Time Log Batch-00001", "status"),
- "Billed")
+ self.assertEquals(webnotes.conn.get_value("Time Log Batch", "_T-Time Log Batch-00001",
+ "status"), "Billed")
self.assertEquals(webnotes.conn.get_value("Time Log", "_T-Time Log-00001", "status"),
"Billed")
si.cancel()
- self.assertEquals(webnotes.conn.get_value("Time Log Batch", "_T-Time Log Batch-00001", "status"),
- "Submitted")
+ self.assertEquals(webnotes.conn.get_value("Time Log Batch", "_T-Time Log Batch-00001",
+ "status"), "Submitted")
self.assertEquals(webnotes.conn.get_value("Time Log", "_T-Time Log-00001", "status"),
"Batched for Billing")
+ def test_sales_invoice_gl_entry_without_aii(self):
+ webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
+ si = webnotes.bean(webnotes.copy_doclist(test_records[1]))
+ si.insert()
+ si.submit()
+
+ gl_entries = webnotes.conn.sql("""select account, debit, credit
+ from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
+ order by account asc""", si.doc.name, as_dict=1)
+ self.assertTrue(gl_entries)
+
+ expected_values = sorted([
+ [si.doc.debit_to, 630.0, 0.0],
+ [test_records[1][1]["income_account"], 0.0, 500.0],
+ [test_records[1][2]["account_head"], 0.0, 80.0],
+ [test_records[1][3]["account_head"], 0.0, 50.0],
+ ])
+
+ for i, gle in enumerate(gl_entries):
+ self.assertEquals(expected_values[i][0], gle.account)
+ self.assertEquals(expected_values[i][1], gle.debit)
+ self.assertEquals(expected_values[i][2], gle.credit)
+
+ # cancel
+ si.cancel()
+
+ gle_count = webnotes.conn.sql("""select count(name) from `tabGL Entry`
+ where voucher_type='Sales Invoice' and voucher_no=%s
+ and ifnull(is_cancelled, 'No') = 'Yes'
+ order by account asc""", si.doc.name)
+
+ self.assertEquals(gle_count[0][0], 8)
+
+ def test_sales_invoice_gl_entry_with_aii_delivery_note(self):
+ webnotes.conn.sql("delete from `tabStock Ledger Entry`")
+
+ webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
+
+ self._insert_purchase_receipt()
+ dn = self._insert_delivery_note()
+
+ si_against_dn = webnotes.copy_doclist(test_records[1])
+ si_against_dn[1]["delivery_note"] = dn.doc.name
+ si_against_dn[1]["dn_detail"] = dn.doclist[1].name
+ si = webnotes.bean(si_against_dn)
+ si.insert()
+
+ si.submit()
+
+ gl_entries = webnotes.conn.sql("""select account, debit, credit
+ from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
+ order by account asc""", si.doc.name, as_dict=1)
+ self.assertTrue(gl_entries)
+
+ expected_values = sorted([
+ [si.doc.debit_to, 630.0, 0.0],
+ [test_records[1][1]["income_account"], 0.0, 500.0],
+ [test_records[1][2]["account_head"], 0.0, 80.0],
+ [test_records[1][3]["account_head"], 0.0, 50.0],
+ ["Stock Delivered But Not Billed - _TC", 0.0, 375.0],
+ [test_records[1][1]["expense_account"], 375.0, 0.0]
+ ])
+ for i, gle in enumerate(gl_entries):
+ self.assertEquals(expected_values[i][0], gle.account)
+ self.assertEquals(expected_values[i][1], gle.debit)
+ self.assertEquals(expected_values[i][2], gle.credit)
+
+ si.cancel()
+ gl_entries = webnotes.conn.sql("""select account, debit, credit
+ from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
+ and ifnull(is_cancelled, 'No') = 'No'
+ order by account asc, name asc""", si.doc.name, as_dict=1)
+
+ expected_values = sorted([
+ [si.doc.debit_to, 630.0, 0.0],
+ [si.doc.debit_to, 0.0, 630.0],
+ [test_records[1][1]["income_account"], 0.0, 500.0],
+ [test_records[1][1]["income_account"], 500.0, 0.0],
+ [test_records[1][2]["account_head"], 0.0, 80.0],
+ [test_records[1][2]["account_head"], 80.0, 0.0],
+ [test_records[1][3]["account_head"], 0.0, 50.0],
+ [test_records[1][3]["account_head"], 50.0, 0.0],
+ ["Stock Delivered But Not Billed - _TC", 0.0, 375.0],
+ ["Stock Delivered But Not Billed - _TC", 375.0, 0.0],
+ [test_records[1][1]["expense_account"], 375.0, 0.0],
+ [test_records[1][1]["expense_account"], 0.0, 375.0]
+
+ ])
+ for i, gle in enumerate(gl_entries):
+ self.assertEquals(expected_values[i][0], gle.account)
+ self.assertEquals(expected_values[i][1], gle.debit)
+ self.assertEquals(expected_values[i][2], gle.credit)
+
+ webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
+
+ def test_pos_gl_entry_with_aii(self):
+ webnotes.conn.sql("delete from `tabStock Ledger Entry`")
+ webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
+
+ self._insert_purchase_receipt()
+ self._insert_pos_settings()
+
+ pos = webnotes.copy_doclist(test_records[1])
+ pos[0]["is_pos"] = 1
+ pos[0]["update_stock"] = 1
+ pos[0]["posting_time"] = "12:05"
+ pos[0]["cash_bank_account"] = "_Test Account Bank Account - _TC"
+ pos[0]["paid_amount"] = 600.0
+
+ si = webnotes.bean(pos)
+ si.insert()
+ si.submit()
+
+ # check stock ledger entries
+ sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry`
+ where voucher_type = 'Sales Invoice' and voucher_no = %s""", si.doc.name, as_dict=1)[0]
+ self.assertTrue(sle)
+ self.assertEquals([sle.item_code, sle.warehouse, sle.actual_qty],
+ ["_Test Item", "_Test Warehouse", -5.0])
+
+ # check gl entries
+ stock_in_hand_account = webnotes.conn.get_value("Company", "_Test Company",
+ "stock_in_hand_account")
+
+ gl_entries = webnotes.conn.sql("""select account, debit, credit
+ from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
+ order by account asc, debit asc""", si.doc.name, as_dict=1)
+ self.assertTrue(gl_entries)
+
+ expected_gl_entries = sorted([
+ [si.doc.debit_to, 630.0, 0.0],
+ [test_records[1][1]["income_account"], 0.0, 500.0],
+ [test_records[1][2]["account_head"], 0.0, 80.0],
+ [test_records[1][3]["account_head"], 0.0, 50.0],
+ [stock_in_hand_account, 0.0, 375.0],
+ [test_records[1][1]["expense_account"], 375.0, 0.0],
+ [si.doc.debit_to, 0.0, 600.0],
+ ["_Test Account Bank Account - _TC", 600.0, 0.0]
+ ])
+ for i, gle in enumerate(gl_entries):
+ self.assertEquals(expected_gl_entries[i][0], gle.account)
+ self.assertEquals(expected_gl_entries[i][1], gle.debit)
+ self.assertEquals(expected_gl_entries[i][2], gle.credit)
+
+ # cancel
+ si.cancel()
+ gl_count = webnotes.conn.sql("""select count(name)
+ from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
+ and ifnull(is_cancelled, 'No') = 'Yes'
+ order by account asc, name asc""", si.doc.name)
+
+ self.assertEquals(gl_count[0][0], 16)
+
+ webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
+
+ def test_sales_invoice_gl_entry_with_aii_no_item_code(self):
+ webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
+
+ si_copy = webnotes.copy_doclist(test_records[1])
+ si_copy[1]["item_code"] = None
+ si = webnotes.bean(si_copy)
+ si.insert()
+ si.submit()
+
+ gl_entries = webnotes.conn.sql("""select account, debit, credit
+ from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
+ order by account asc""", si.doc.name, as_dict=1)
+ self.assertTrue(gl_entries)
+
+ expected_values = sorted([
+ [si.doc.debit_to, 630.0, 0.0],
+ [test_records[1][1]["income_account"], 0.0, 500.0],
+ [test_records[1][2]["account_head"], 0.0, 80.0],
+ [test_records[1][3]["account_head"], 0.0, 50.0],
+ ])
+ for i, gle in enumerate(gl_entries):
+ self.assertEquals(expected_values[i][0], gle.account)
+ self.assertEquals(expected_values[i][1], gle.debit)
+ self.assertEquals(expected_values[i][2], gle.credit)
+
+ webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
+
+ def test_sales_invoice_gl_entry_with_aii_non_stock_item(self):
+ webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
+
+ si_copy = webnotes.copy_doclist(test_records[1])
+ si_copy[1]["item_code"] = "_Test Non Stock Item"
+ si = webnotes.bean(si_copy)
+ si.insert()
+ si.submit()
+
+ gl_entries = webnotes.conn.sql("""select account, debit, credit
+ from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
+ order by account asc""", si.doc.name, as_dict=1)
+ self.assertTrue(gl_entries)
+
+ expected_values = sorted([
+ [si.doc.debit_to, 630.0, 0.0],
+ [test_records[1][1]["income_account"], 0.0, 500.0],
+ [test_records[1][2]["account_head"], 0.0, 80.0],
+ [test_records[1][3]["account_head"], 0.0, 50.0],
+ ])
+ for i, gle in enumerate(gl_entries):
+ self.assertEquals(expected_values[i][0], gle.account)
+ self.assertEquals(expected_values[i][1], gle.debit)
+ self.assertEquals(expected_values[i][2], gle.credit)
+
+ webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
+
+
+
+ def _insert_purchase_receipt(self):
+ from stock.doctype.purchase_receipt.test_purchase_receipt import test_records \
+ as pr_test_records
+ pr = webnotes.bean(copy=pr_test_records[0])
+ pr.run_method("calculate_taxes_and_totals")
+ pr.insert()
+ pr.submit()
+
+ def _insert_delivery_note(self):
+ from stock.doctype.delivery_note.test_delivery_note import test_records \
+ as dn_test_records
+ dn = webnotes.bean(copy=dn_test_records[0])
+ dn.insert()
+ dn.submit()
+ return dn
+
+ def _insert_pos_settings(self):
+ ps = webnotes.bean([
+ {
+ "cash_bank_account": "_Test Account Bank Account - _TC",
+ "company": "_Test Company",
+ "conversion_rate": 1.0,
+ "cost_center": "_Test Cost Center - _TC",
+ "currency": "INR",
+ "doctype": "POS Setting",
+ "income_account": "_Test Account Bank Account - _TC",
+ "price_list_name": "_Test Price List",
+ "territory": "_Test Territory",
+ "warehouse": "_Test Warehouse"
+ }
+ ])
+ ps.insert()
test_dependencies = ["Journal Voucher"]
-test_records = [[
- {
- "naming_series": "_T-Sales Invoice-",
- "company": "_Test Company",
- "conversion_rate": 1.0,
- "currency": "INR",
- "debit_to": "_Test Customer - _TC",
- "customer": "_Test Customer",
- "customer_name": "_Test Customer",
- "doctype": "Sales Invoice",
- "due_date": "2013-01-23",
- "fiscal_year": "_Test Fiscal Year 2013",
- "grand_total": 561.8,
- "grand_total_export": 561.8,
- "net_total": 500.0,
- "plc_conversion_rate": 1.0,
- "posting_date": "2013-01-23",
- "price_list_currency": "INR",
- "price_list_name": "_Test Price List",
- "territory": "_Test Territory"
- },
- {
- "amount": 500.0,
- "basic_rate": 500.0,
- "description": "138-CMS Shoe",
- "doctype": "Sales Invoice Item",
- "export_amount": 500.0,
- "export_rate": 500.0,
- "income_account": "Sales - _TC",
- "cost_center": "_Test Cost Center - _TC",
- "item_name": "138-CMS Shoe",
- "parentfield": "entries",
- "qty": 1.0
- },
- {
- "account_head": "_Test Account VAT - _TC",
- "charge_type": "On Net Total",
- "description": "VAT",
- "doctype": "Sales Taxes and Charges",
- "parentfield": "other_charges",
- "tax_amount": 30.0,
- },
- {
- "account_head": "_Test Account Service Tax - _TC",
- "charge_type": "On Net Total",
- "description": "Service Tax",
- "doctype": "Sales Taxes and Charges",
- "parentfield": "other_charges",
- "tax_amount": 31.8,
- }
-]]
\ No newline at end of file
+test_records = [
+ [
+ {
+ "naming_series": "_T-Sales Invoice-",
+ "company": "_Test Company",
+ "conversion_rate": 1.0,
+ "currency": "INR",
+ "debit_to": "_Test Customer - _TC",
+ "customer": "_Test Customer",
+ "customer_name": "_Test Customer",
+ "doctype": "Sales Invoice",
+ "due_date": "2013-01-23",
+ "fiscal_year": "_Test Fiscal Year 2013",
+ "grand_total": 561.8,
+ "grand_total_export": 561.8,
+ "net_total": 500.0,
+ "plc_conversion_rate": 1.0,
+ "posting_date": "2013-01-23",
+ "price_list_currency": "INR",
+ "price_list_name": "_Test Price List",
+ "territory": "_Test Territory"
+ },
+ {
+ "amount": 500.0,
+ "basic_rate": 500.0,
+ "description": "138-CMS Shoe",
+ "doctype": "Sales Invoice Item",
+ "export_amount": 500.0,
+ "export_rate": 500.0,
+ "income_account": "Sales - _TC",
+ "cost_center": "_Test Cost Center - _TC",
+ "item_name": "138-CMS Shoe",
+ "parentfield": "entries",
+ "qty": 1.0
+ },
+ {
+ "account_head": "_Test Account VAT - _TC",
+ "charge_type": "On Net Total",
+ "description": "VAT",
+ "doctype": "Sales Taxes and Charges",
+ "parentfield": "other_charges",
+ "tax_amount": 30.0,
+ },
+ {
+ "account_head": "_Test Account Service Tax - _TC",
+ "charge_type": "On Net Total",
+ "description": "Service Tax",
+ "doctype": "Sales Taxes and Charges",
+ "parentfield": "other_charges",
+ "tax_amount": 31.8,
+ },
+ {
+ "parentfield": "sales_team",
+ "doctype": "Sales Team",
+ "sales_person": "_Test Sales Person 1",
+ "allocated_percentage": 65.5,
+ },
+ {
+ "parentfield": "sales_team",
+ "doctype": "Sales Team",
+ "sales_person": "_Test Sales Person 2",
+ "allocated_percentage": 34.5,
+ },
+ ],
+ [
+ {
+ "naming_series": "_T-Sales Invoice-",
+ "company": "_Test Company",
+ "conversion_rate": 1.0,
+ "currency": "INR",
+ "debit_to": "_Test Customer - _TC",
+ "customer": "_Test Customer",
+ "customer_name": "_Test Customer",
+ "doctype": "Sales Invoice",
+ "due_date": "2013-01-23",
+ "fiscal_year": "_Test Fiscal Year 2013",
+ "grand_total": 630.0,
+ "grand_total_export": 630.0,
+ "net_total": 500.0,
+ "plc_conversion_rate": 1.0,
+ "posting_date": "2013-03-07",
+ "price_list_currency": "INR",
+ "price_list_name": "_Test Price List",
+ "territory": "_Test Territory"
+ },
+ {
+ "item_code": "_Test Item",
+ "item_name": "_Test Item",
+ "description": "_Test Item",
+ "doctype": "Sales Invoice Item",
+ "parentfield": "entries",
+ "qty": 5.0,
+ "basic_rate": 500.0,
+ "amount": 500.0,
+ "export_rate": 500.0,
+ "export_amount": 500.0,
+ "income_account": "Sales - _TC",
+ "expense_account": "_Test Account Cost for Goods Sold - _TC",
+ "cost_center": "_Test Cost Center - _TC",
+ },
+ {
+ "account_head": "_Test Account VAT - _TC",
+ "charge_type": "On Net Total",
+ "description": "VAT",
+ "doctype": "Sales Taxes and Charges",
+ "parentfield": "other_charges",
+ "tax_amount": 80.0,
+ },
+ {
+ "account_head": "_Test Account Service Tax - _TC",
+ "charge_type": "On Net Total",
+ "description": "Service Tax",
+ "doctype": "Sales Taxes and Charges",
+ "parentfield": "other_charges",
+ "tax_amount": 50.0,
+ }
+ ],
+]
\ No newline at end of file
diff --git a/accounts/doctype/sales_invoice_item/sales_invoice_item.txt b/accounts/doctype/sales_invoice_item/sales_invoice_item.txt
index c8b18a48809..ca078b53f42 100644
--- a/accounts/doctype/sales_invoice_item/sales_invoice_item.txt
+++ b/accounts/doctype/sales_invoice_item/sales_invoice_item.txt
@@ -1,8 +1,8 @@
[
{
- "creation": "2013-03-05 09:11:04",
+ "creation": "2013-03-07 11:42:55",
"docstatus": 0,
- "modified": "2013-03-07 07:03:30",
+ "modified": "2013-03-11 14:58:50",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -30,7 +30,8 @@
"fieldname": "barcode",
"fieldtype": "Data",
"label": "Barcode",
- "print_hide": 1
+ "print_hide": 1,
+ "read_only": 0
},
{
"doctype": "DocField",
@@ -42,6 +43,7 @@
"oldfieldtype": "Link",
"options": "Item",
"print_hide": 0,
+ "read_only": 0,
"reqd": 0,
"search_index": 1
},
@@ -63,6 +65,7 @@
"oldfieldname": "item_name",
"oldfieldtype": "Data",
"print_hide": 1,
+ "read_only": 0,
"reqd": 1,
"search_index": 0
},
@@ -74,6 +77,7 @@
"oldfieldname": "description",
"oldfieldtype": "Text",
"print_width": "200px",
+ "read_only": 0,
"reqd": 1,
"width": "200px"
},
@@ -84,6 +88,7 @@
"label": "Qty",
"oldfieldname": "qty",
"oldfieldtype": "Currency",
+ "read_only": 0,
"reqd": 0
},
{
@@ -102,6 +107,7 @@
"oldfieldtype": "Currency",
"options": "currency",
"print_hide": 1,
+ "read_only": 0,
"reqd": 0
},
{
@@ -111,7 +117,8 @@
"label": "Discount (%)",
"oldfieldname": "adj_rate",
"oldfieldtype": "Float",
- "print_hide": 1
+ "print_hide": 1,
+ "read_only": 0
},
{
"doctype": "DocField",
@@ -121,6 +128,7 @@
"oldfieldname": "export_rate",
"oldfieldtype": "Currency",
"options": "currency",
+ "read_only": 0,
"reqd": 1
},
{
@@ -155,6 +163,7 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
+ "read_only": 0,
"reqd": 1,
"search_index": 0
},
@@ -179,7 +188,8 @@
"oldfieldname": "warehouse",
"oldfieldtype": "Link",
"options": "Warehouse",
- "print_hide": 1
+ "print_hide": 1,
+ "read_only": 0
},
{
"doctype": "DocField",
@@ -192,9 +202,20 @@
"options": "Account",
"print_hide": 1,
"print_width": "120px",
+ "read_only": 0,
"reqd": 1,
"width": "120px"
},
+ {
+ "doctype": "DocField",
+ "fieldname": "expense_account",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "in_filter": 1,
+ "label": "Expense Account",
+ "options": "Account",
+ "print_hide": 1
+ },
{
"doctype": "DocField",
"fieldname": "cost_center",
@@ -206,6 +227,7 @@
"options": "Cost Center",
"print_hide": 1,
"print_width": "120px",
+ "read_only": 0,
"reqd": 0,
"width": "120px"
},
@@ -217,7 +239,8 @@
"label": "Serial No",
"oldfieldname": "serial_no",
"oldfieldtype": "Small Text",
- "print_hide": 0
+ "print_hide": 0,
+ "read_only": 0
},
{
"doctype": "DocField",
@@ -225,7 +248,8 @@
"fieldtype": "Link",
"label": "Batch No",
"options": "Batch",
- "print_hide": 1
+ "print_hide": 1,
+ "read_only": 0
},
{
"doctype": "DocField",
@@ -249,7 +273,8 @@
"label": "Brand Name",
"oldfieldname": "brand",
"oldfieldtype": "Data",
- "print_hide": 1
+ "print_hide": 1,
+ "read_only": 0
},
{
"doctype": "DocField",
@@ -328,7 +353,8 @@
"fieldname": "time_log_batch",
"fieldtype": "Link",
"label": "Time Log Batch",
- "options": "Time Log Batch"
+ "options": "Time Log Batch",
+ "read_only": 0
},
{
"doctype": "DocField",
@@ -353,6 +379,17 @@
"print_hide": 1,
"read_only": 1
},
+ {
+ "doctype": "DocField",
+ "fieldname": "buying_amount",
+ "fieldtype": "Currency",
+ "hidden": 1,
+ "label": "Buying Amount",
+ "no_copy": 1,
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
"allow_on_submit": 1,
"doctype": "DocField",
@@ -361,6 +398,7 @@
"label": "Page Break",
"no_copy": 1,
"print_hide": 1,
+ "read_only": 0,
"report_hide": 1
}
]
\ No newline at end of file
diff --git a/accounts/general_ledger.py b/accounts/general_ledger.py
index 215c3514216..8e0f4082bc9 100644
--- a/accounts/general_ledger.py
+++ b/accounts/general_ledger.py
@@ -16,7 +16,7 @@
from __future__ import unicode_literals
import webnotes
-from webnotes.utils import flt, cstr
+from webnotes.utils import flt, cstr, now
from webnotes.model.doc import Document
def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True,
@@ -109,5 +109,7 @@ def validate_total_debit_credit(total_debit, total_credit):
(total_debit - total_credit), raise_exception=1)
def set_as_cancel(voucher_type, voucher_no):
- webnotes.conn.sql("""update `tabGL Entry` set is_cancelled='Yes'
- where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
\ No newline at end of file
+ webnotes.conn.sql("""update `tabGL Entry` set is_cancelled='Yes',
+ modified=%s, modified_by=%s
+ where voucher_type=%s and voucher_no=%s""",
+ (now(), webnotes.session.user, voucher_type, voucher_no))
\ No newline at end of file
diff --git a/accounts/page/accounts_browser/accounts_browser.js b/accounts/page/accounts_browser/accounts_browser.js
index 6fd0c66d6a5..97c8554ac8c 100644
--- a/accounts/page/accounts_browser/accounts_browser.js
+++ b/accounts/page/accounts_browser/accounts_browser.js
@@ -109,11 +109,11 @@ erpnext.AccountsChart = Class.extend({
},
onrender: function(treenode) {
- if (ctype == 'Account') {
- var bal = treenode.data && treenode.data.balance.split(' ') || ['',''];
- if (bal && flt(bal[1])) {
+ if (ctype == 'Account' && treenode.data) {
+ if(treenode.data.balance) {
treenode.parent.append(''
- + format_currency(bal[1], bal[0]) + ' ');
+ + format_currency(treenode.data.balance, treenode.data.currency)
+ + '');
}
}
}
diff --git a/accounts/page/accounts_browser/accounts_browser.py b/accounts/page/accounts_browser/accounts_browser.py
index 68f835733d5..d78b8a2503d 100644
--- a/accounts/page/accounts_browser/accounts_browser.py
+++ b/accounts/page/accounts_browser/accounts_browser.py
@@ -1,7 +1,7 @@
from __future__ import unicode_literals
import webnotes
import webnotes.defaults
-
+from webnotes.utils import flt
from accounts.utils import get_balance_on
@webnotes.whitelist()
@@ -53,6 +53,7 @@ def get_children():
currency = webnotes.conn.sql("select default_currency from `tabCompany` where name = %s", company)[0][0]
for each in acc:
bal = get_balance_on(each.get("value"))
- each['balance'] = currency + ' ' + str(bal or 0)
+ each["currency"] = currency
+ each["balance"] = flt(bal)
return acc
diff --git a/accounts/page/financial_analytics/financial_analytics.js b/accounts/page/financial_analytics/financial_analytics.js
index f0bafdb07bd..f7145490a13 100644
--- a/accounts/page/financial_analytics/financial_analytics.js
+++ b/accounts/page/financial_analytics/financial_analytics.js
@@ -71,9 +71,11 @@ erpnext.FinancialAnalytics = erpnext.AccountTreeGrid.extend({
setup_filters: function() {
var me = this;
this._super();
- this.filter_inputs.pl_or_bs.change(function() {
- me.filter_inputs.refresh.click();
- }).add_options($.map(wn.report_dump.data["Cost Center"], function(v) {return v.name;}));
+ this.trigger_refresh_on_change(["pl_or_bs"]);
+
+ this.filter_inputs.pl_or_bs
+ .add_options($.map(wn.report_dump.data["Cost Center"], function(v) {return v.name;}));
+
this.setup_plot_check();
},
init_filter_values: function() {
diff --git a/accounts/page/general_ledger/general_ledger.js b/accounts/page/general_ledger/general_ledger.js
index 8f6b598d566..4a3f21ea926 100644
--- a/accounts/page/general_ledger/general_ledger.js
+++ b/accounts/page/general_ledger/general_ledger.js
@@ -108,7 +108,7 @@ erpnext.GeneralLedger = wn.views.GridReport.extend({
// filter accounts options by company
this.filter_inputs.company.change(function() {
me.setup_account_filter(this);
- me.filter_inputs.refresh.click();
+ me.set_route()
});
this.filter_inputs.account.change(function() {
diff --git a/accounts/report/gross_profit/gross_profit.py b/accounts/report/gross_profit/gross_profit.py
index fa926dacde2..f1ae00e13f0 100644
--- a/accounts/report/gross_profit/gross_profit.py
+++ b/accounts/report/gross_profit/gross_profit.py
@@ -25,7 +25,7 @@ def execute(filters=None):
for row in delivery_note_items:
selling_amount = flt(row.amount)
buying_amount = get_buying_amount(row.item_code, row.warehouse,
- row.qty, row.name, row.item_row, stock_ledger_entries, item_sales_bom)
+ row.qty, "Delivery Note", row.name, row.item_row, stock_ledger_entries, item_sales_bom)
if selling_amount:
gross_profit = selling_amount - buying_amount
gross_profit_percent = (gross_profit / selling_amount) * 100.0
diff --git a/buying/doctype/purchase_common/purchase_common.js b/buying/doctype/purchase_common/purchase_common.js
index 05b7bcbef84..dacee80e55d 100644
--- a/buying/doctype/purchase_common/purchase_common.js
+++ b/buying/doctype/purchase_common/purchase_common.js
@@ -21,7 +21,7 @@
wn.provide("erpnext.buying");
-erpnext.buying.BuyingController = erpnext.utils.Controller.extend({
+erpnext.buying.BuyingController = wn.ui.form.Controller.extend({
setup: function() {
var me = this;
@@ -68,15 +68,15 @@ erpnext.buying.BuyingController = erpnext.utils.Controller.extend({
callback: function(r) {
if(!r.exc) {
me.price_list_currency();
- if (callback_fn) callback_fn(me.frm.doc, me.frm.doc.doctype,
- me.frm.doc.name);
+ if (typeof callback_fn === "function")
+ callback_fn(me.frm.doc, me.frm.doc.doctype, me.frm.doc.name);
}
}
});
} else {
me.price_list_currency();
- if (callback_fn) callback_fn(me.frm.doc, me.frm.doc.doctype,
- me.frm.doc.name);
+ if (typeof callback_fn === "function")
+ callback_fn(me.frm.doc, me.frm.doc.doctype, me.frm.doc.name);
}
}
},
diff --git a/buying/doctype/purchase_order/purchase_order.py b/buying/doctype/purchase_order/purchase_order.py
index 438442cf247..218d4bfeee0 100644
--- a/buying/doctype/purchase_order/purchase_order.py
+++ b/buying/doctype/purchase_order/purchase_order.py
@@ -132,6 +132,10 @@ class DocType(BuyingController):
for d in getlist(self.doclist, 'po_details'):
#1. Check if is_stock_item == 'Yes'
if webnotes.conn.get_value("Item", d.item_code, "is_stock_item") == "Yes":
+ # this happens when item is changed from non-stock to stock item
+ if not d.warehouse:
+ continue
+
ind_qty, po_qty = 0, flt(d.qty) * flt(d.conversion_factor)
if is_stopped:
po_qty = flt(d.qty) > flt(d.received_qty) and \
diff --git a/buying/page/purchase_analytics/purchase_analytics.js b/buying/page/purchase_analytics/purchase_analytics.js
index 7d8171ebbd3..fc082eae13e 100644
--- a/buying/page/purchase_analytics/purchase_analytics.js
+++ b/buying/page/purchase_analytics/purchase_analytics.js
@@ -120,19 +120,9 @@ erpnext.PurchaseAnalytics = wn.views.TreeGridReport.extend({
setup_filters: function() {
var me = this;
this._super();
-
- this.filter_inputs.value_or_qty.change(function() {
- me.filter_inputs.refresh.click();
- });
-
- this.filter_inputs.tree_type.change(function() {
- me.filter_inputs.refresh.click();
- });
-
- this.filter_inputs.based_on.change(function() {
- me.filter_inputs.refresh.click();
- });
+ this.trigger_refresh_on_change(["value_or_qty", "tree_type", "based_on"]);
+
this.show_zero_check()
this.setup_plot_check();
},
diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py
index aa52b5e4124..576921a5303 100644
--- a/controllers/accounts_controller.py
+++ b/controllers/accounts_controller.py
@@ -21,8 +21,11 @@ from webnotes.utils import flt
from utilities.transaction_base import TransactionBase
class AccountsController(TransactionBase):
- def get_gl_dict(self, args, cancel):
+ def get_gl_dict(self, args, cancel=None):
"""this method populates the common properties of a gl entry record"""
+ if cancel is None:
+ cancel = (self.doc.docstatus == 2)
+
gl_dict = {
'company': self.doc.company,
'posting_date': self.doc.posting_date,
diff --git a/controllers/selling_controller.py b/controllers/selling_controller.py
index 94a56e33007..40606c31989 100644
--- a/controllers/selling_controller.py
+++ b/controllers/selling_controller.py
@@ -37,4 +37,27 @@ class SellingController(AccountsController):
self.doc.grand_total or self.doc.rounded_total, company_currency)
if self.meta.get_field("in_words_export"):
self.doc.in_words_export = money_in_words(disable_rounded_total and
- self.doc.grand_total_export or self.doc.rounded_total_export, self.doc.currency)
\ No newline at end of file
+ self.doc.grand_total_export or self.doc.rounded_total_export, self.doc.currency)
+
+ def get_stock_ledger_entries(self):
+ item_list, warehouse_list = self.get_distinct_item_warehouse()
+ if item_list and warehouse_list:
+ return webnotes.conn.sql("""select item_code, voucher_type, voucher_no,
+ voucher_detail_no, posting_date, posting_time, stock_value,
+ warehouse, actual_qty as qty from `tabStock Ledger Entry`
+ where ifnull(`is_cancelled`, "No") = "No" and company = %s
+ and item_code in (%s) and warehouse in (%s)
+ order by item_code desc, warehouse desc, posting_date desc,
+ posting_time desc, name desc""" %
+ ('%s', ', '.join(['%s']*len(item_list)), ', '.join(['%s']*len(warehouse_list))),
+ tuple([self.doc.company] + item_list + warehouse_list), as_dict=1)
+
+ def get_distinct_item_warehouse(self):
+ item_list = []
+ warehouse_list = []
+ for item in self.doclist.get({"parentfield": self.fname}) \
+ + self.doclist.get({"parentfield": "packing_details"}):
+ item_list.append(item.item_code)
+ warehouse_list.append(item.warehouse)
+
+ return list(set(item_list)), list(set(warehouse_list))
\ No newline at end of file
diff --git a/home/page/attributions/attributions.html b/home/page/attributions/attributions.html
index 07da9fd89d6..2d08c79dd0f 100644
--- a/home/page/attributions/attributions.html
+++ b/home/page/attributions/attributions.html
@@ -26,6 +26,10 @@
Python Programming Language
The "batteries included" language that lets you write elegant code, quickly. Python Libraries:
diff --git a/home/page/latest_updates/latest_updates.js b/home/page/latest_updates/latest_updates.js
index b387aad67a4..84db37287ff 100644
--- a/home/page/latest_updates/latest_updates.js
+++ b/home/page/latest_updates/latest_updates.js
@@ -1,6 +1,15 @@
erpnext.updates = [
+ ["12th March", ["Updates to website module. Added more options in Style Settings and Website Settings."]],
+ ["5th March", ["Refactored Upload Attendance Tool"]],
+ ["4th March", ["Lead organization added in Quotation classic/spartan/modern print format"]],
["1st March", [
- "Time Log, Time Log Batch: Created feature to batch Time Logs so that they can be tracked for billing."
+ "Time Log, Time Log Batch: Created feature to batch Time Logs so that they can be tracked for billing.",
+ "Sub-contracting code refactored for PO",
+ ]],
+ ["28th February", [
+ "Datatype validation in Voucher Import Tool",
+ "Fixes for conversion factor in old invoices",
+ "Fixed asynchronus issue in purchase cycle"
]],
["27th February", [
"Time Log: Created Time Log System, with Calendar View."
diff --git a/hr/doctype/employee/employee.py b/hr/doctype/employee/employee.py
index 2bd79981595..d98c8a7754b 100644
--- a/hr/doctype/employee/employee.py
+++ b/hr/doctype/employee/employee.py
@@ -17,7 +17,7 @@
from __future__ import unicode_literals
import webnotes
-from webnotes.utils import getdate, validate_email_add
+from webnotes.utils import getdate, validate_email_add, cstr
from webnotes.model.doc import make_autoname
from webnotes import msgprint, _
@@ -104,7 +104,7 @@ class DocType:
fname, fid = file_args.split(",")
if self.doc.image == fname:
new_file_args = fname + "," + fid
- file_list = profile_wrapper.doc.file_list.split("\n")
+ file_list = cstr(profile_wrapper.doc.file_list).split("\n")
if new_file_args not in file_list:
file_list += [new_file_args]
profile_wrapper.doc.file_list = "\n".join(file_list)
diff --git a/hr/doctype/upload_attendance/upload_attendance.js b/hr/doctype/upload_attendance/upload_attendance.js
index 008e1cd878b..0c1d7b2574b 100644
--- a/hr/doctype/upload_attendance/upload_attendance.js
+++ b/hr/doctype/upload_attendance/upload_attendance.js
@@ -18,7 +18,7 @@
wn.require("public/app/js/utils.js");
wn.provide("erpnext.hr");
-erpnext.hr.AttendanceControlPanel = erpnext.utils.Controller.extend({
+erpnext.hr.AttendanceControlPanel = wn.ui.form.Controller.extend({
onload: function() {
this.frm.set_value("att_fr_date", get_today());
this.frm.set_value("att_to_date", get_today());
diff --git a/hr/search_criteria/monthly_attendance_details/monthly_attendance_details.sql b/hr/search_criteria/monthly_attendance_details/monthly_attendance_details.sql
index 7487fb40105..762a94f7fbd 100644
--- a/hr/search_criteria/monthly_attendance_details/monthly_attendance_details.sql
+++ b/hr/search_criteria/monthly_attendance_details/monthly_attendance_details.sql
@@ -1 +1 @@
-SELECT DISTINCT `tabAttendance`.employee, `tabAttendance`.employee_name FROM `tabAttendance` WHERE `tabAttendance`.fiscal_year like '%(fiscal_year)s%%' AND `tabAttendance`.`company` like '%(company)s%%' AND `tabAttendance`.`employee` like '%(employee)s%%'
\ No newline at end of file
+SELECT DISTINCT `tabAttendance`.employee, `tabEmployee`.employee_name FROM `tabAttendance`, `tabEmployee` WHERE `tabEmployee`.name = `tabAttendance`.employee and `tabAttendance`.fiscal_year like '%(fiscal_year)s%%' AND `tabAttendance`.company like '%(company)s%%' AND `tabAttendance`.employee like '%(employee)s%%'
\ No newline at end of file
diff --git a/patches/december_2012/clear_web_cache.py b/patches/december_2012/clear_web_cache.py
deleted file mode 100644
index b92f4bde088..00000000000
--- a/patches/december_2012/clear_web_cache.py
+++ /dev/null
@@ -1,13 +0,0 @@
-import webnotes
-def execute():
- webnotes.reload_doc("website", "doctype", "web_page")
- webnotes.reload_doc("website", "doctype", "blog")
- webnotes.reload_doc("stock", "doctype", "item")
- webnotes.reload_doc("setup", "doctype", "item_group")
-
- # build wn-web.js and wn-web.css
- from website.helpers.make_web_include_files import make
- make()
-
- import website.utils
- website.utils.clear_cache()
\ No newline at end of file
diff --git a/patches/february_2013/p07_clear_web_cache.py b/patches/february_2013/p07_clear_web_cache.py
deleted file mode 100644
index 5aca2d6ee6a..00000000000
--- a/patches/february_2013/p07_clear_web_cache.py
+++ /dev/null
@@ -1,6 +0,0 @@
-import webnotes
-
-def execute():
- from website.utils import clear_cache
- clear_cache()
-
\ No newline at end of file
diff --git a/patches/march_2013/p03_rename_blog_to_blog_post.py b/patches/march_2013/p03_rename_blog_to_blog_post.py
new file mode 100644
index 00000000000..69902f34bee
--- /dev/null
+++ b/patches/march_2013/p03_rename_blog_to_blog_post.py
@@ -0,0 +1,9 @@
+import webnotes
+
+def execute():
+ webnotes.reload_doc('website', 'doctype', 'blogger')
+ webnotes.rename_doc("DocType", "Blog", "Blog Post", force=True)
+ webnotes.reload_doc('website', 'doctype', 'blog_post')
+ webnotes.conn.sql('''update tabBlogger set posts=(select count(*)
+ from `tabBlog Post` where ifnull(blogger,"")=tabBlogger.name)''')
+ webnotes.conn.sql("""update `tabBlog Post` set published_on=date(creation)""")
diff --git a/patches/march_2013/p03_update_buying_amount.py b/patches/march_2013/p03_update_buying_amount.py
new file mode 100644
index 00000000000..e45a3dbd1c1
--- /dev/null
+++ b/patches/march_2013/p03_update_buying_amount.py
@@ -0,0 +1,10 @@
+import webnotes
+
+def execute():
+ dn_list = webnotes.conn.sql("""select name from `tabDelivery Note` where docstatus < 2""")
+ for dn in dn_list:
+ webnotes.bean("Delivery Note", dn[0]).set_buying_amount()
+
+ si_list = webnotes.conn.sql("""select name from `tabSales Invoice` where docstatus < 2""")
+ for si in si_list:
+ webnotes.bean("Sales Invoice", si[0]).set_buying_amount()
\ No newline at end of file
diff --git a/patches/march_2013/p05_payment_reconciliation.py b/patches/march_2013/p05_payment_reconciliation.py
new file mode 100644
index 00000000000..f2f03064d6c
--- /dev/null
+++ b/patches/march_2013/p05_payment_reconciliation.py
@@ -0,0 +1,30 @@
+import webnotes
+
+def execute():
+ # delete wrong gle entries created due to a bug in make_gl_entries of Account Controller
+ # when using payment reconciliation
+ res = webnotes.conn.sql_list("""select distinct gl1.voucher_no
+ from `tabGL Entry` gl1, `tabGL Entry` gl2
+ where
+ (date(gl1.modified) between "2013-03-11" and "2013-03-15")
+ and date(gl1.modified) = date(gl2.modified)
+ and gl1.voucher_no = gl2.voucher_no
+ and gl1.voucher_type = "Journal Voucher"
+ and gl1.voucher_type = gl2.voucher_type
+ and gl1.posting_date = gl2.posting_date
+ and gl1.account = gl2.account
+ and ifnull(gl1.cost_center, "") = ifnull(gl2.cost_center, "")
+ and ifnull(gl1.is_cancelled, 'No') = 'No' and ifnull(gl2.is_cancelled, 'No') = 'No'
+ and ifnull(gl1.against_voucher, '') = ifnull(gl2.against_voucher, '')
+ and ifnull(gl1.against_voucher_type, '') = ifnull(gl2.against_voucher_type, '')
+ and gl1.remarks = gl2.remarks
+ and ifnull(gl1.debit, 0) = ifnull(gl2.credit, 0)
+ and ifnull(gl1.credit, 0) = ifnull(gl2.debit, 0)
+ and gl1.name > gl2.name""")
+
+ for r in res:
+ webnotes.conn.sql("""update `tabGL Entry` set `is_cancelled`='Yes'
+ where voucher_type='Journal Voucher' and voucher_no=%s""", r)
+ jv = webnotes.bean("Journal Voucher", r)
+ jv.run_method("make_gl_entries")
+
\ No newline at end of file
diff --git a/patches/patch_list.py b/patches/patch_list.py
index d136820c2e4..f5e3f40916d 100644
--- a/patches/patch_list.py
+++ b/patches/patch_list.py
@@ -16,7 +16,9 @@
from __future__ import unicode_literals
patch_list = [
- "execute:webnotes.reload_doc('core', 'doctype', 'report') # 2013-03-07",
+ "execute:webnotes.reload_doc('core', 'doctype', 'docfield')",
+ "execute:webnotes.reload_doc('core', 'doctype', 'report')",
+ "execute:webnotes.reload_doc('core', 'doctype', 'doctype')",
"patches.mar_2012.so_rv_mapper_fix",
"patches.mar_2012.clean_property_setter",
"patches.april_2012.naming_series_patch",
@@ -130,7 +132,6 @@ patch_list = [
"patches.december_2012.fix_default_print_format",
"patches.december_2012.file_list_rename",
"patches.december_2012.replace_createlocal",
- "patches.december_2012.clear_web_cache",
"patches.december_2012.remove_quotation_next_contact",
"patches.december_2012.stock_entry_cleanup",
"patches.december_2012.production_order_naming_series",
@@ -187,7 +188,6 @@ patch_list = [
"execute:webnotes.delete_doc('DocType', 'Service Order Detail')",
"execute:webnotes.delete_doc('DocType', 'Service Quotation Detail')",
"patches.february_2013.p06_material_request_mappers",
- "patches.february_2013.p07_clear_web_cache",
"execute:webnotes.delete_doc('Page', 'Query Report')",
"execute:webnotes.delete_doc('Search Criteria', 'employeewise_balance_leave_report')",
"execute:webnotes.delete_doc('Search Criteria', 'employee_leave_balance_report')",
@@ -209,4 +209,7 @@ patch_list = [
"execute:webnotes.conn.sql('update tabDocPerm set `submit`=1, `cancel`=1, `amend`=1 where parent=\"Time Log\"')",
"execute:webnotes.delete_doc('DocType', 'Attendance Control Panel')",
"patches.march_2013.p02_get_global_default",
+ "patches.march_2013.p03_rename_blog_to_blog_post",
+ "execute:webnotes.reload_doc('hr', 'search_criteria', 'monthly_attendance_details')",
+ "patches.march_2013.p05_payment_reconciliation",
]
\ No newline at end of file
diff --git a/projects/doctype/task/task.js b/projects/doctype/task/task.js
index 472ca6b98cd..84939205402 100644
--- a/projects/doctype/task/task.js
+++ b/projects/doctype/task/task.js
@@ -18,7 +18,7 @@ wn.provide("erpnext.projects");
cur_frm.add_fetch("project", "company", "company");
-erpnext.projects.Task = erpnext.utils.Controller.extend({
+erpnext.projects.Task = wn.ui.form.Controller.extend({
setup: function() {
this.frm.fields_dict.project.get_query = function() {
return "select name from `tabProject` \
@@ -29,7 +29,8 @@ erpnext.projects.Task = erpnext.utils.Controller.extend({
project: function() {
if(this.frm.doc.project) {
- get_server_fields('get_project_details', '','', doc, cdt, cdn, 1);
+ get_server_fields('get_project_details', '','', this.frm.doc, this.frm.doc.doctype,
+ this.frm.doc.name, 1);
}
},
diff --git a/public/js/controllers/stock_controller.js b/public/js/controllers/stock_controller.js
index d3511e1c033..15d34e0e335 100644
--- a/public/js/controllers/stock_controller.js
+++ b/public/js/controllers/stock_controller.js
@@ -16,7 +16,7 @@
wn.provide("erpnext.stock");
-erpnext.stock.StockController = erpnext.utils.Controller.extend({
+erpnext.stock.StockController = wn.ui.form.Controller.extend({
show_stock_ledger: function() {
var me = this;
this.frm.add_custom_button("Show Stock Ledger", function() {
diff --git a/public/js/feature_setup.js b/public/js/feature_setup.js
index 0304034cf6b..85c848df03d 100644
--- a/public/js/feature_setup.js
+++ b/public/js/feature_setup.js
@@ -166,22 +166,24 @@ pscript.feature_dict = {
'Address': {'fields':['sales_partner']},
'Contact': {'fields':['sales_partner']},
'Customer': {'fields':['sales_team']},
- 'Delivery Note': {'fields':['sales_team','Packing List']},
+ 'Delivery Note': {'fields':['sales_team','packing_list']},
'Item': {'fields':['item_customer_details']},
- 'Sales Invoice': {'fields':['sales_team']},
- 'Sales Order': {'fields':['sales_team','Packing List']}
+ 'Sales Invoice': {'fields':['sales_team', 'packing_list']},
+ 'Sales Order': {'fields':['sales_team','packing_list']}
},
'fs_more_info': {
- 'Delivery Note': {'fields':['More Info']},
- 'Opportunity': {'fields':['More Info']},
- 'Material Request': {'fields':['More Info']},
- 'Lead': {'fields':['More Info']},
- 'Purchase Invoice': {'fields':['More Info']},
- 'Purchase Order': {'fields':['More Info']},
- 'Purchase Receipt': {'fields':['More Info']},
- 'Quotation': {'fields':['More Info']},
- 'Sales Invoice': {'fields':['More Info']},
- 'Sales Order': {'fields':['More Info']},
+ "Customer Issue": {"fields": ["more_info"]},
+ 'Material Request': {'fields':['more_info']},
+ 'Lead': {'fields':['more_info']},
+ 'Opportunity': {'fields':['more_info']},
+ 'Purchase Invoice': {'fields':['more_info']},
+ 'Purchase Order': {'fields':['more_info']},
+ 'Purchase Receipt': {'fields':['more_info']},
+ 'Supplier Quotation': {'fields':['more_info']},
+ 'Quotation': {'fields':['more_info']},
+ 'Sales Invoice': {'fields':['more_info']},
+ 'Sales Order': {'fields':['more_info']},
+ 'Delivery Note': {'fields':['more_info']},
},
'fs_quality': {
'Item': {'fields':['Item Inspection Criteria','inspection_required']},
@@ -199,25 +201,23 @@ pscript.feature_dict = {
}
$(document).bind('form_refresh', function() {
- for(sys_feat in sys_defaults)
- {
- if(sys_defaults[sys_feat]=='0' && (sys_feat in pscript.feature_dict)) //"Features to hide" exists
- {
- if(cur_frm.doc.doctype in pscript.feature_dict[sys_feat])
- {
- for(fort in pscript.feature_dict[sys_feat][cur_frm.doc.doctype])
- {
- if(fort=='fields')
+ for(sys_feat in sys_defaults) {
+ if(sys_defaults[sys_feat]=='0'
+ && (sys_feat in pscript.feature_dict)) { //"Features to hide" exists
+
+ if(cur_frm.doc.doctype in pscript.feature_dict[sys_feat]) {
+ for(fort in pscript.feature_dict[sys_feat][cur_frm.doc.doctype]) {
+ if(fort=='fields') {
hide_field(pscript.feature_dict[sys_feat][cur_frm.doc.doctype][fort]);
- else if(cur_frm.fields_dict[fort])
- {
+ } else if(cur_frm.fields_dict[fort]) {
for(grid_field in pscript.feature_dict[sys_feat][cur_frm.doc.doctype][fort])
cur_frm.fields_dict[fort].grid.set_column_disp(pscript.feature_dict[sys_feat][cur_frm.doc.doctype][fort][grid_field], false);
- }
- else
+ } else {
msgprint('Grid "'+fort+'" does not exists');
+ }
}
}
+
}
}
})
diff --git a/public/js/stock_analytics.js b/public/js/stock_analytics.js
index d6a994cd1c5..c3ed1cb232f 100644
--- a/public/js/stock_analytics.js
+++ b/public/js/stock_analytics.js
@@ -134,6 +134,7 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({
var data = wn.report_dump.data["Stock Ledger Entry"];
this.item_warehouse = {};
+ this.serialized_buying_rates = this.get_serialized_buying_rates();
for(var i=0, j=data.length; i 0 && sle.serial_no) {
+ $.each(sle.serial_no.trim().split("\n"), function(i, sr) {
+ if(sr && sle.incoming_rate !== undefined) {
+ serialized_buying_rates[sr] = flt(sle.incoming_rate);
+ }
+ });
+ }
+ });
+
+ return serialized_buying_rates;
+ },
});
\ No newline at end of file
diff --git a/public/js/utils.js b/public/js/utils.js
index 0f78705294a..4df9555ae9b 100644
--- a/public/js/utils.js
+++ b/public/js/utils.js
@@ -23,35 +23,4 @@ erpnext.get_currency = function(company) {
return wn.model.get(":Company", company).default_currency || wn.boot.sysdefaults.currency;
else
return wn.boot.sysdefaults.currency;
-}
-
-// TODO
-erpnext.utils.Controller = Class.extend({
- init: function(opts) {
- $.extend(this, opts);
- this.setup && this.setup();
- },
-
- onload_post_render: function() {
- if(this.frm.doc.__islocal) {
- this.setup_defaults();
- }
- },
-
- setup_defaults: function() {
- var me = this;
-
- var defaults = {
- posting_date: wn.datetime.get_today(),
- posting_time: wn.datetime.now_time()
- }
-
- $.each(defaults, function(k, v) {
- if(!me.frm.doc[k]) me.frm.set_value(k, v);
- });
- },
-
- refresh: function() {
- erpnext.hide_naming_series();
- }
-});
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/selling/doctype/sales_common/sales_common.py b/selling/doctype/sales_common/sales_common.py
index 47d139f9553..12ae4a8c909 100644
--- a/selling/doctype/sales_common/sales_common.py
+++ b/selling/doctype/sales_common/sales_common.py
@@ -341,12 +341,10 @@ class DocType(TransactionBase):
# ========================================================================
# it indicates % contribution of sales person in sales
def get_allocated_sum(self,obj):
- sum = 0
- for d in getlist(obj.doclist,'sales_team'):
- sum += flt(d.allocated_percentage)
- if (flt(sum) != 100) and getlist(obj.doclist,'sales_team'):
- msgprint("Total Allocated % of Sales Persons should be 100%")
- raise Exception
+ sales_team_list = obj.doclist.get({"parentfield": "sales_team"})
+ total_allocation = sum([flt(d.allocated_percentage) for d in sales_team_list])
+ if sales_team_list and total_allocation != 100.0:
+ msgprint("Total Allocated %% of Sales Persons should be 100%", raise_exception=True)
# Check Conversion Rate (i.e. it will not allow conversion rate to be 1 for Currency other than default currency set in Global Defaults)
# ===========================================================================
diff --git a/selling/doctype/sales_order/sales_order.py b/selling/doctype/sales_order/sales_order.py
index 8205afbd447..5009c4ee261 100644
--- a/selling/doctype/sales_order/sales_order.py
+++ b/selling/doctype/sales_order/sales_order.py
@@ -156,9 +156,13 @@ class DocType(SellingController):
f = [d.item_code, d.description]
#check item is stock item
- st_itm = sql("select is_stock_item from `tabItem` where name = '%s'"%d.item_code)
+ st_itm = sql("select is_stock_item from `tabItem` where name = %s", d.item_code)
if st_itm and st_itm[0][0] == 'Yes':
+ if not d.reserved_warehouse:
+ msgprint("""Please enter Reserved Warehouse for item %s
+ as it is stock Item""" % d.item_code, raise_exception=1)
+
if e in check_list:
msgprint("Item %s has been entered twice." % d.item_code)
else:
@@ -333,10 +337,6 @@ class DocType(SellingController):
def update_stock_ledger(self, update_stock, is_stopped = 0):
for d in self.get_item_list(is_stopped):
if webnotes.conn.get_value("Item", d['item_code'], "is_stock_item") == "Yes":
- if not d['reserved_warehouse']:
- msgprint("""Please enter Reserved Warehouse for item %s
- as it is stock Item""" % d['item_code'], raise_exception=1)
-
args = {
"item_code": d['item_code'],
"reserved_qty": flt(update_stock) * flt(d['reserved_qty']),
diff --git a/selling/doctype/sales_order/test_sales_order.py b/selling/doctype/sales_order/test_sales_order.py
index 5d820fe769b..40a10b439c0 100644
--- a/selling/doctype/sales_order/test_sales_order.py
+++ b/selling/doctype/sales_order/test_sales_order.py
@@ -65,7 +65,7 @@ class TestSalesOrder(unittest.TestCase):
# submit dn
dn = self.create_dn_against_so(so)
- self.check_reserved_qty(so.doclist[1].item_code, so.doclist[1].reserved_warehouse, 6.0)
+ self.check_reserved_qty(so.doclist[1].item_code, so.doclist[1].reserved_warehouse, 5.0)
# stop so
so.load_from_db()
@@ -75,7 +75,7 @@ class TestSalesOrder(unittest.TestCase):
# unstop so
so.load_from_db()
so.obj.unstop_sales_order()
- self.check_reserved_qty(so.doclist[1].item_code, so.doclist[1].reserved_warehouse, 6.0)
+ self.check_reserved_qty(so.doclist[1].item_code, so.doclist[1].reserved_warehouse, 5.0)
# cancel dn
dn.cancel()
@@ -151,9 +151,9 @@ class TestSalesOrder(unittest.TestCase):
dn = self.create_dn_against_so(so)
self.check_reserved_qty(sbom_test_records[0][1]["item_code"],
- so.doclist[1].reserved_warehouse, 30.0)
+ so.doclist[1].reserved_warehouse, 25.0)
self.check_reserved_qty(sbom_test_records[0][2]["item_code"],
- so.doclist[1].reserved_warehouse, 12.0)
+ so.doclist[1].reserved_warehouse, 10.0)
# stop so
so.load_from_db()
@@ -168,9 +168,9 @@ class TestSalesOrder(unittest.TestCase):
so.load_from_db()
so.obj.unstop_sales_order()
self.check_reserved_qty(sbom_test_records[0][1]["item_code"],
- so.doclist[1].reserved_warehouse, 30.0)
+ so.doclist[1].reserved_warehouse, 25.0)
self.check_reserved_qty(sbom_test_records[0][2]["item_code"],
- so.doclist[1].reserved_warehouse, 12.0)
+ so.doclist[1].reserved_warehouse, 10.0)
# cancel dn
dn.cancel()
@@ -234,8 +234,8 @@ test_records = [
"price_list_name": "_Test Price List",
"territory": "_Test Territory",
"transaction_date": "2013-02-21",
- "grand_total": 500.0,
- "grand_total_export": 500.0,
+ "grand_total": 1000.0,
+ "grand_total_export": 1000.0,
},
{
"description": "CPU",
@@ -244,9 +244,9 @@ test_records = [
"item_name": "CPU",
"parentfield": "sales_order_details",
"qty": 10.0,
- "basic_rate": 50.0,
- "export_rate": 50.0,
- "amount": 500.0,
+ "basic_rate": 100.0,
+ "export_rate": 100.0,
+ "amount": 1000.0,
"reserved_warehouse": "_Test Warehouse",
}
],
diff --git a/selling/page/sales_analytics/sales_analytics.js b/selling/page/sales_analytics/sales_analytics.js
index 499c6c01563..0b35af5f31e 100644
--- a/selling/page/sales_analytics/sales_analytics.js
+++ b/selling/page/sales_analytics/sales_analytics.js
@@ -122,18 +122,8 @@ erpnext.SalesAnalytics = wn.views.TreeGridReport.extend({
setup_filters: function() {
var me = this;
this._super();
-
- this.filter_inputs.value_or_qty.change(function() {
- me.filter_inputs.refresh.click();
- });
-
- this.filter_inputs.tree_type.change(function() {
- me.filter_inputs.refresh.click();
- });
- this.filter_inputs.based_on.change(function() {
- me.filter_inputs.refresh.click();
- });
+ this.trigger_refresh_on_change(["value_or_qty", "tree_type", "based_on"]);
this.show_zero_check()
this.setup_plot_check();
diff --git a/setup/doctype/sales_person/test_sales_person.py b/setup/doctype/sales_person/test_sales_person.py
index 5af450916b1..2dea3e5deec 100644
--- a/setup/doctype/sales_person/test_sales_person.py
+++ b/setup/doctype/sales_person/test_sales_person.py
@@ -4,5 +4,19 @@ test_records = [
"sales_person_name": "_Test Sales Person",
"parent_sales_person": "All Sales Persons",
"is_group": "No"
+ }],
+ [{
+ "doctype": "Sales Person",
+ "sales_person_name": "_Test Sales Person 1",
+ "parent_sales_person": "All Sales Persons",
+ "is_group": "No"
+ }],
+ [{
+ "doctype": "Sales Person",
+ "sales_person_name": "_Test Sales Person 2",
+ "parent_sales_person": "All Sales Persons",
+ "is_group": "No"
}]
+
+
]
\ No newline at end of file
diff --git a/setup/doctype/setup_control/setup_control.py b/setup/doctype/setup_control/setup_control.py
index 00cf1dee4a1..5bfe4a7d94b 100644
--- a/setup/doctype/setup_control/setup_control.py
+++ b/setup/doctype/setup_control/setup_control.py
@@ -97,7 +97,7 @@ class DocType:
self.create_email_digest()
webnotes.clear_cache()
- msgprint("Company setup is complete")
+ msgprint("Company setup is complete. Please refresh the page before continuing.")
import webnotes.utils
user_fullname = (args.get('first_name') or '') + (args.get('last_name')
diff --git a/setup/page/setup/setup.js b/setup/page/setup/setup.js
index e970a60c247..a9df4592f94 100644
--- a/setup/page/setup/setup.js
+++ b/setup/page/setup/setup.js
@@ -45,7 +45,7 @@ wn.module_page["Setup"] = [
},
{
"doctype":"Workflow",
- label:wn._("Workfow"),
+ label:wn._("Workflow"),
"description":wn._("Set workflow rules.")
},
{
@@ -98,12 +98,6 @@ wn.module_page["Setup"] = [
label:wn._("Print Heading"),
"description":wn._("Add headers for standard print formats")
},
- {
- "route":"Form/Style Settings/Style Settings",
- doctype:wn._("Style Settings"),
- label:wn._("Style Settings"),
- "description":wn._("Change background fonts etc")
- }
]
},
{
diff --git a/startup/report_data_map.py b/startup/report_data_map.py
index ba3b546b2c0..f914277cc34 100644
--- a/startup/report_data_map.py
+++ b/startup/report_data_map.py
@@ -86,8 +86,9 @@ data_map = {
"order_by": "name"
},
"Stock Ledger Entry": {
- "columns": ["name", "posting_date", "posting_time", "item_code", "warehouse", "actual_qty as qty",
- "voucher_type", "voucher_no", "ifnull(incoming_rate,0) as incoming_rate", "stock_uom"],
+ "columns": ["name", "posting_date", "posting_time", "item_code", "warehouse",
+ "actual_qty as qty", "voucher_type", "voucher_no",
+ "ifnull(incoming_rate,0) as incoming_rate", "stock_uom", "serial_no"],
"conditions": ["ifnull(is_cancelled, 'No')='No'"],
"order_by": "posting_date, posting_time, name",
"links": {
diff --git a/stock/doctype/delivery_note/delivery_note.py b/stock/doctype/delivery_note/delivery_note.py
index c0b99166ee2..229ec40a549 100644
--- a/stock/doctype/delivery_note/delivery_note.py
+++ b/stock/doctype/delivery_note/delivery_note.py
@@ -156,7 +156,7 @@ class DocType(SellingController):
if not self.doc.billing_status: self.doc.billing_status = 'Not Billed'
if not self.doc.installation_status: self.doc.installation_status = 'Not Installed'
-
+
def validate_mandatory(self):
if self.doc.amended_from and not self.doc.amendment_date:
msgprint("Please Enter Amendment Date")
@@ -225,7 +225,12 @@ class DocType(SellingController):
bin = sql("select actual_qty, projected_qty from `tabBin` where item_code = %s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1)
d.actual_qty = bin and flt(bin[0]['actual_qty']) or 0
d.projected_qty = bin and flt(bin[0]['projected_qty']) or 0
-
+
+ def on_update(self):
+ self.doclist = get_obj('Sales Common').make_packing_list(self,'delivery_note_details')
+ sl = get_obj('Stock Ledger')
+ sl.scrub_serial_nos(self)
+ sl.scrub_serial_nos(self, 'packing_details')
def on_submit(self):
self.validate_packed_qty()
@@ -252,6 +257,7 @@ class DocType(SellingController):
self.credit_limit()
+ self.set_buying_amount()
self.make_gl_entries()
# set DN status
@@ -332,10 +338,10 @@ class DocType(SellingController):
self.values = []
for d in self.get_item_list():
if webnotes.conn.get_value("Item", d['item_code'], "is_stock_item") == "Yes":
- if not d['warehouse']:
- msgprint("Please enter Warehouse for item %s as it is stock item"
- % d['item_code'], raise_exception=1)
-
+ # this happens when item is changed from non-stock to stock item
+ if not d["warehouse"]:
+ continue
+
if d['reserved_qty'] < 0 :
# Reduce reserved qty from reserved warehouse mentioned in so
args = {
@@ -387,13 +393,28 @@ class DocType(SellingController):
if amount != 0:
total = (amount/self.doc.net_total)*self.doc.grand_total
get_obj('Sales Common').check_credit(self, total)
-
-
- def on_update(self):
- self.doclist = get_obj('Sales Common').make_packing_list(self,'delivery_note_details')
- sl = get_obj('Stock Ledger')
- sl.scrub_serial_nos(self)
- sl.scrub_serial_nos(self, 'packing_details')
+
+ def set_buying_amount(self):
+ from stock.utils import get_buying_amount, get_sales_bom
+ stock_ledger_entries = self.get_stock_ledger_entries()
+ item_sales_bom = get_sales_bom()
+
+ if stock_ledger_entries:
+ for item in self.doclist.get({"parentfield": "delivery_note_details"}):
+ item.buying_amount = get_buying_amount(item.item_code, item.warehouse, item.qty,
+ self.doc.doctype, self.doc.name, item.name, stock_ledger_entries,
+ item_sales_bom)
+ webnotes.conn.set_value("Delivery Note Item", item.name, "buying_amount",
+ item.buying_amount)
+
+ self.validate_warehouse()
+
+ def validate_warehouse(self):
+ for d in self.get_item_list():
+ if webnotes.conn.get_value("Item", d['item_code'], "is_stock_item") == "Yes":
+ if not d['warehouse']:
+ msgprint("Please enter Warehouse for item %s as it is stock item"
+ % d['item_code'], raise_exception=1)
def make_gl_entries(self):
if not cint(webnotes.defaults.get_global_default("auto_inventory_accounting")):
@@ -426,38 +447,6 @@ class DocType(SellingController):
make_gl_entries(gl_entries, cancel=self.doc.docstatus == 2)
def get_total_buying_amount(self):
- from stock.utils import get_buying_amount, get_sales_bom
- stock_ledger_entries = self.get_stock_ledger_entries()
- item_sales_bom = get_sales_bom()
- total_buying_amount = 0
-
- if stock_ledger_entries:
- for item in self.doclist.get({"parentfield": "delivery_note_details"}):
- buying_amount = get_buying_amount(item.item_code, item.warehouse, item.qty,
- self.doc.name, item.name, stock_ledger_entries, item_sales_bom)
- total_buying_amount += buying_amount
-
+ total_buying_amount = sum([item.buying_amount for item in
+ self.doclist.get({"parentfield": "delivery_note_details"})])
return total_buying_amount
-
- def get_stock_ledger_entries(self):
- item_list, warehouse_list = self.get_distinct_item_warehouse()
- if item_list and warehouse_list:
- return webnotes.conn.sql("""select item_code, voucher_type, voucher_no,
- voucher_detail_no, posting_date, posting_time, stock_value,
- warehouse, actual_qty as qty from `tabStock Ledger Entry`
- where ifnull(`is_cancelled`, "No") = "No" and company = %s
- and item_code in (%s) and warehouse in (%s)
- order by item_code desc, warehouse desc, posting_date desc,
- posting_time desc, name desc""" %
- ('%s', ', '.join(['%s']*len(item_list)), ', '.join(['%s']*len(warehouse_list))),
- tuple([self.doc.company] + item_list + warehouse_list), as_dict=1)
-
- def get_distinct_item_warehouse(self):
- item_list = []
- warehouse_list = []
- for item in self.doclist.get({"parentfield": "delivery_note_details"}) \
- + self.doclist.get({"parentfield": "packing_details"}):
- item_list.append(item.item_code)
- warehouse_list.append(item.warehouse)
-
- return list(set(item_list)), list(set(warehouse_list))
\ No newline at end of file
diff --git a/stock/doctype/delivery_note/test_delivery_note.py b/stock/doctype/delivery_note/test_delivery_note.py
index c2bb5d07ca0..d0b440cfee4 100644
--- a/stock/doctype/delivery_note/test_delivery_note.py
+++ b/stock/doctype/delivery_note/test_delivery_note.py
@@ -48,6 +48,8 @@ class TestDeliveryNote(unittest.TestCase):
def test_delivery_note_gl_entry(self):
webnotes.conn.sql("""delete from `tabBin`""")
+ webnotes.conn.sql("delete from `tabStock Ledger Entry`")
+
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
self.assertEqual(cint(webnotes.defaults.get_global_default("auto_inventory_accounting")), 1)
@@ -109,7 +111,7 @@ test_records = [
"description": "CPU",
"doctype": "Delivery Note Item",
"item_code": "_Test Item",
- "item_name": "CPU",
+ "item_name": "_Test Item",
"parentfield": "delivery_note_details",
"qty": 5.0,
"basic_rate": 100.0,
diff --git a/stock/doctype/delivery_note_item/delivery_note_item.txt b/stock/doctype/delivery_note_item/delivery_note_item.txt
index 985a0727563..47b0d33bcda 100644
--- a/stock/doctype/delivery_note_item/delivery_note_item.txt
+++ b/stock/doctype/delivery_note_item/delivery_note_item.txt
@@ -1,8 +1,8 @@
[
{
- "creation": "2013-02-22 01:28:00",
+ "creation": "2013-03-07 11:42:59",
"docstatus": 0,
- "modified": "2013-03-07 07:03:20",
+ "modified": "2013-03-07 15:46:43",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -30,7 +30,8 @@
"fieldname": "barcode",
"fieldtype": "Data",
"label": "Barcode",
- "print_hide": 1
+ "print_hide": 1,
+ "read_only": 0
},
{
"doctype": "DocField",
@@ -42,6 +43,7 @@
"oldfieldtype": "Link",
"options": "Item",
"print_width": "150px",
+ "read_only": 0,
"reqd": 1,
"search_index": 1,
"width": "150px"
@@ -64,6 +66,7 @@
"oldfieldtype": "Data",
"print_hide": 1,
"print_width": "150px",
+ "read_only": 0,
"reqd": 1,
"width": "150px"
},
@@ -75,6 +78,7 @@
"oldfieldname": "description",
"oldfieldtype": "Small Text",
"print_width": "300px",
+ "read_only": 0,
"reqd": 1,
"width": "300px"
},
@@ -87,6 +91,7 @@
"oldfieldname": "qty",
"oldfieldtype": "Currency",
"print_width": "100px",
+ "read_only": 0,
"reqd": 1,
"width": "100px"
},
@@ -115,6 +120,7 @@
"options": "currency",
"print_hide": 1,
"print_width": "100px",
+ "read_only": 0,
"reqd": 0,
"width": "100px"
},
@@ -128,6 +134,7 @@
"oldfieldtype": "Float",
"print_hide": 1,
"print_width": "100px",
+ "read_only": 0,
"width": "100px"
},
{
@@ -140,6 +147,7 @@
"options": "currency",
"print_hide": 0,
"print_width": "150px",
+ "read_only": 0,
"reqd": 0,
"width": "150px"
},
@@ -181,6 +189,7 @@
"options": "Company:company:default_currency",
"print_hide": 1,
"print_width": "150px",
+ "read_only": 0,
"reqd": 0,
"width": "150px"
},
@@ -208,6 +217,7 @@
"options": "Warehouse",
"print_hide": 1,
"print_width": "100px",
+ "read_only": 0,
"width": "100px"
},
{
@@ -219,7 +229,8 @@
"no_copy": 1,
"oldfieldname": "serial_no",
"oldfieldtype": "Text",
- "print_hide": 0
+ "print_hide": 0,
+ "read_only": 0
},
{
"doctype": "DocField",
@@ -229,7 +240,8 @@
"oldfieldname": "batch_no",
"oldfieldtype": "Link",
"options": "Batch",
- "print_hide": 1
+ "print_hide": 1,
+ "read_only": 0
},
{
"doctype": "DocField",
@@ -375,6 +387,17 @@
"print_hide": 1,
"read_only": 1
},
+ {
+ "doctype": "DocField",
+ "fieldname": "buying_amount",
+ "fieldtype": "Currency",
+ "hidden": 1,
+ "label": "Buying Amount",
+ "no_copy": 1,
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
"allow_on_submit": 1,
"doctype": "DocField",
@@ -383,6 +406,7 @@
"label": "Page Break",
"oldfieldname": "page_break",
"oldfieldtype": "Check",
- "print_hide": 1
+ "print_hide": 1,
+ "read_only": 0
}
]
\ No newline at end of file
diff --git a/stock/doctype/item/item.py b/stock/doctype/item/item.py
index 334af298e91..931b7762d39 100644
--- a/stock/doctype/item/item.py
+++ b/stock/doctype/item/item.py
@@ -20,15 +20,12 @@ import webnotes
from webnotes.utils import cstr, flt
from webnotes.model.doc import addchild
from webnotes.model.bean import getlist
-from webnotes import msgprint
+from webnotes import msgprint, _
sql = webnotes.conn.sql
-class DocType:
- def __init__(self, doc, doclist=[]):
- self.doc = doc
- self.doclist = doclist
-
+from webnotes.model.controller import DocListController
+class DocType(DocListController):
def get_tax_rate(self, tax_type):
rate = sql("select tax_rate from tabAccount where name = %s", tax_type)
ret = {
@@ -196,6 +193,8 @@ class DocType:
if self.doc.name:
self.old_page_name = webnotes.conn.get_value('Item', self.doc.name, 'page_name')
+
+ self.validate_is_stock_item()
def check_non_asset_warehouse(self):
if self.doc.is_asset_item == "Yes":
@@ -215,6 +214,15 @@ class DocType:
'description' : file and file[0]['description'] or ''
}
return ret
+
+ def validate_is_stock_item(self):
+ if not self.doc.fields.get("__islocal"):
+ if webnotes.conn.get_value("Item", self.doc.name, "is_stock_item")=="Yes" and \
+ ((not self.doc.is_stock_item) or self.doc.is_stock_item == "No"):
+ if self.check_if_sle_exists() == "exists":
+ webnotes.msgprint(self.meta.get_label("is_stock_item") + ": "
+ + _("""Cannot change to Yes. Reason: Stock Ledger Entries exist for""")
+ + """ "%s" """ % self.doc.name, raise_exception=True)
def check_if_sle_exists(self):
sle = sql("select name from `tabStock Ledger Entry` where item_code = %s and ifnull(is_cancelled, 'No') = 'No'", self.doc.name)
@@ -230,8 +238,7 @@ class DocType:
from website.helpers.product import get_parent_item_groups, url_for_website
self.parent_groups = get_parent_item_groups(self.doc.item_group) + [{"name":self.doc.name}]
self.doc.website_image = url_for_website(self.doc.website_image)
- self.doc.title = self.doc.item_name == self.doc.name and self.doc.item_name or \
- (self.doc.item_name + " [" + self.doc.name + "]")
+ self.doc.title = self.doc.item_name
if self.doc.slideshow:
from website.helpers.slideshow import get_slideshow
diff --git a/stock/doctype/item/test_item.py b/stock/doctype/item/test_item.py
index 035774b50bd..f31f245e814 100644
--- a/stock/doctype/item/test_item.py
+++ b/stock/doctype/item/test_item.py
@@ -127,4 +127,23 @@ test_records = [
"is_sub_contracted_item": "Yes",
"stock_uom": "_Test UOM"
}],
+ [{
+ "doctype": "Item",
+ "item_code": "_Test Non Stock Item",
+ "item_name": "_Test Non Stock Item",
+ "description": "_Test Non Stock Item",
+ "item_group": "_Test Item Group Desktops",
+ "is_stock_item": "No",
+ "is_asset_item": "No",
+ "has_batch_no": "No",
+ "has_serial_no": "No",
+ "is_purchase_item": "Yes",
+ "is_sales_item": "Yes",
+ "is_service_item": "No",
+ "is_sample_item": "No",
+ "inspection_required": "No",
+ "is_pro_applicable": "No",
+ "is_sub_contracted_item": "No",
+ "stock_uom": "_Test UOM"
+ }],
]
\ No newline at end of file
diff --git a/stock/doctype/purchase_receipt/purchase_receipt.py b/stock/doctype/purchase_receipt/purchase_receipt.py
index 12da0a6ee87..cce1493141f 100644
--- a/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -125,7 +125,7 @@ class DocType(BuyingController):
self.update_raw_materials_supplied("pr_raw_material_details")
self.update_valuation_rate("purchase_receipt_details")
-
+
def on_update(self):
if self.doc.rejected_warehouse:
for d in getlist(self.doclist,'purchase_receipt_details'):
@@ -146,6 +146,9 @@ class DocType(BuyingController):
self.values = []
for d in getlist(self.doclist, 'purchase_receipt_details'):
if webnotes.conn.get_value("Item", d.item_code, "is_stock_item") == "Yes":
+ if not d.warehouse:
+ continue
+
ord_qty = 0
pr_qty = flt(d.qty) * flt(d.conversion_factor)
diff --git a/stock/doctype/stock_entry/stock_entry.js b/stock/doctype/stock_entry/stock_entry.js
index 55a86a3799d..ba1f64802ab 100644
--- a/stock/doctype/stock_entry/stock_entry.js
+++ b/stock/doctype/stock_entry/stock_entry.js
@@ -19,7 +19,6 @@ wn.provide("erpnext.stock");
erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
onload_post_render: function() {
- this._super();
if(this.frm.doc.__islocal && (this.frm.doc.production_order || this.frm.doc.bom_no)
&& !getchildren('Stock Entry Detail', this.frm.doc.name, 'mtn_details').length) {
// if production order / bom is mentioned, get items
@@ -28,7 +27,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
},
refresh: function() {
- this._super();
+ erpnext.hide_naming_series();
this.toggle_related_fields(this.frm.doc);
this.toggle_enable_bom();
if (this.frm.doc.docstatus==1) {
diff --git a/stock/doctype/stock_entry/stock_entry.py b/stock/doctype/stock_entry/stock_entry.py
index 278c283284a..cd20266d6be 100644
--- a/stock/doctype/stock_entry/stock_entry.py
+++ b/stock/doctype/stock_entry/stock_entry.py
@@ -29,9 +29,9 @@ import json
sql = webnotes.conn.sql
-from utilities.transaction_base import TransactionBase
+from controllers.accounts_controller import AccountsController
-class DocType(TransactionBase):
+class DocType(AccountsController):
def __init__(self, doc, doclist=[]):
self.doc = doc
self.doclist = doclist
@@ -39,11 +39,11 @@ class DocType(TransactionBase):
def validate(self):
self.validate_purpose()
-
self.validate_serial_nos()
pro_obj = self.doc.production_order and \
get_obj('Production Order', self.doc.production_order) or None
+ self.validate_item()
self.validate_warehouse(pro_obj)
self.validate_production_order(pro_obj)
self.get_stock_and_rate()
@@ -51,20 +51,19 @@ class DocType(TransactionBase):
self.validate_bom()
self.validate_finished_goods()
self.validate_return_reference_doc()
-
self.validate_with_material_request()
def on_submit(self):
self.update_serial_no(1)
self.update_stock_ledger(0)
- # update Production Order
self.update_production_order(1)
+ self.make_gl_entries()
def on_cancel(self):
self.update_serial_no(0)
self.update_stock_ledger(1)
- # update Production Order
self.update_production_order(0)
+ self.make_gl_entries()
def validate_purpose(self):
valid_purposes = ["Material Issue", "Material Receipt", "Material Transfer",
@@ -78,6 +77,12 @@ class DocType(TransactionBase):
sl_obj.scrub_serial_nos(self)
sl_obj.validate_serial_no(self, 'mtn_details')
+ def validate_item(self):
+ for item in self.doclist.get({"parentfield": "mtn_details"}):
+ if item.item_code not in self.stock_items:
+ msgprint(_("""Only Stock Items are allowed for Stock Entry"""),
+ raise_exception=True)
+
def validate_warehouse(self, pro_obj):
"""perform various (sometimes conditional) validations on warehouse"""
@@ -159,6 +164,47 @@ class DocType(TransactionBase):
elif self.doc.purpose != "Material Transfer":
self.doc.production_order = None
+ def make_gl_entries(self):
+ if not cint(webnotes.defaults.get_global_default("auto_inventory_accounting")):
+ return
+
+ abbr = webnotes.conn.get_value("Company", self.doc.company, "abbr")
+ stock_in_hand_account = self.get_stock_in_hand_account()
+ total_valuation_amount = self.get_total_valuation_amount()
+
+ if total_valuation_amount:
+ gl_entries = [
+ # debit stock in hand account
+ self.get_gl_dict({
+ "account": stock_in_hand_account,
+ "against": "Stock Adjustment - %s" % abbr,
+ "debit": total_valuation_amount,
+ "remarks": self.doc.remarks or "Accounting Entry for Stock",
+ }, self.doc.docstatus == 2),
+
+ # debit stock received but not billed account
+ self.get_gl_dict({
+ "account": "Stock Adjustment - %s" % abbr,
+ "against": stock_in_hand_account,
+ "credit": total_valuation_amount,
+ "cost_center": "Auto Inventory Accounting - %s" % abbr,
+ "remarks": self.doc.remarks or "Accounting Entry for Stock",
+ }, self.doc.docstatus == 2),
+ ]
+ from accounts.general_ledger import make_gl_entries
+ make_gl_entries(gl_entries, cancel=self.doc.docstatus == 2)
+
+ def get_total_valuation_amount(self):
+ total_valuation_amount = 0
+ for item in self.doclist.get({"parentfield": "mtn_details"}):
+ if item.t_warehouse and not item.s_warehouse:
+ total_valuation_amount += flt(item.incoming_rate) * flt(item.transfer_qty)
+
+ if item.s_warehouse and not item.t_warehouse:
+ total_valuation_amount -= flt(item.incoming_rate) * flt(item.transfer_qty)
+
+ return total_valuation_amount
+
def get_stock_and_rate(self):
"""get stock and incoming rate on posting date"""
for d in getlist(self.doclist, 'mtn_details'):
diff --git a/stock/doctype/stock_entry/test_stock_entry.py b/stock/doctype/stock_entry/test_stock_entry.py
index 39ec58ac3a4..a4103c37bb7 100644
--- a/stock/doctype/stock_entry/test_stock_entry.py
+++ b/stock/doctype/stock_entry/test_stock_entry.py
@@ -21,6 +21,143 @@ class TestStockEntry(unittest.TestCase):
where item_code='_Test Item'""")
self.assertTrue(mr_name)
+
+ def test_material_receipt_gl_entry(self):
+ webnotes.conn.sql("delete from `tabStock Ledger Entry`")
+ webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
+
+ mr = webnotes.bean(copy=test_records[0])
+ mr.insert()
+ mr.submit()
+
+ stock_in_hand_account = webnotes.conn.get_value("Company", "_Test Company",
+ "stock_in_hand_account")
+
+ self.check_stock_ledger_entries("Stock Entry", mr.doc.name,
+ [["_Test Item", "_Test Warehouse", 50.0]])
+
+ self.check_gl_entries("Stock Entry", mr.doc.name,
+ sorted([
+ [stock_in_hand_account, 5000.0, 0.0],
+ ["Stock Adjustment - _TC", 0.0, 5000.0]
+ ])
+ )
+
+ mr.cancel()
+ self.check_stock_ledger_entries("Stock Entry", mr.doc.name,
+ sorted([["_Test Item", "_Test Warehouse", 50.0],
+ ["_Test Item", "_Test Warehouse", -50.0]]))
+
+ self.check_gl_entries("Stock Entry", mr.doc.name,
+ sorted([
+ [stock_in_hand_account, 5000.0, 0.0],
+ ["Stock Adjustment - _TC", 0.0, 5000.0],
+ [stock_in_hand_account, 0.0, 5000.0],
+ ["Stock Adjustment - _TC", 5000.0, 0.0]
+ ])
+ )
+
+ webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
+
+ def test_material_issue_gl_entry(self):
+ webnotes.conn.sql("delete from `tabStock Ledger Entry`")
+ webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
+
+ mr = webnotes.bean(copy=test_records[0])
+ mr.insert()
+ mr.submit()
+
+ mi = webnotes.bean(copy=test_records[1])
+ mi.insert()
+ mi.submit()
+
+ stock_in_hand_account = webnotes.conn.get_value("Company", "_Test Company",
+ "stock_in_hand_account")
+
+ self.check_stock_ledger_entries("Stock Entry", mi.doc.name,
+ [["_Test Item", "_Test Warehouse", -40.0]])
+
+ self.check_gl_entries("Stock Entry", mi.doc.name,
+ sorted([
+ [stock_in_hand_account, 0.0, 4000.0],
+ ["Stock Adjustment - _TC", 4000.0, 0.0]
+ ])
+ )
+
+ mi.cancel()
+
+ self.check_stock_ledger_entries("Stock Entry", mi.doc.name,
+ sorted([["_Test Item", "_Test Warehouse", -40.0],
+ ["_Test Item", "_Test Warehouse", 40.0]]))
+
+ self.check_gl_entries("Stock Entry", mi.doc.name,
+ sorted([
+ [stock_in_hand_account, 0.0, 4000.0],
+ ["Stock Adjustment - _TC", 4000.0, 0.0],
+ [stock_in_hand_account, 4000.0, 0.0],
+ ["Stock Adjustment - _TC", 0.0, 4000.0],
+ ])
+ )
+
+ webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
+
+ def test_material_transfer_gl_entry(self):
+ webnotes.conn.sql("delete from `tabStock Ledger Entry`")
+ webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
+
+ mr = webnotes.bean(copy=test_records[0])
+ mr.insert()
+ mr.submit()
+
+ mtn = webnotes.bean(copy=test_records[2])
+ mtn.insert()
+ mtn.submit()
+
+ self.check_stock_ledger_entries("Stock Entry", mtn.doc.name,
+ [["_Test Item", "_Test Warehouse", -45.0], ["_Test Item", "_Test Warehouse 1", 45.0]])
+
+ # no gl entry
+ gl_entries = webnotes.conn.sql("""select * from `tabGL Entry`
+ where voucher_type = 'Stock Entry' and voucher_no=%s""", mtn.doc.name)
+ self.assertFalse(gl_entries)
+
+ mtn.cancel()
+ self.check_stock_ledger_entries("Stock Entry", mtn.doc.name,
+ sorted([["_Test Item", "_Test Warehouse", 45.0],
+ ["_Test Item", "_Test Warehouse 1", -45.0],
+ ["_Test Item", "_Test Warehouse", -45.0],
+ ["_Test Item", "_Test Warehouse 1", 45.0]]))
+
+ # no gl entry
+ gl_entries = webnotes.conn.sql("""select * from `tabGL Entry`
+ where voucher_type = 'Stock Entry' and voucher_no=%s""", mtn.doc.name)
+ self.assertFalse(gl_entries)
+
+ webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
+
+ def check_stock_ledger_entries(self, voucher_type, voucher_no, expected_sle):
+ # check stock ledger entries
+ sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry` where voucher_type = %s
+ and voucher_no = %s order by item_code, warehouse, actual_qty""",
+ (voucher_type, voucher_no), as_dict=1)
+ self.assertTrue(sle)
+
+ for i, sle in enumerate(sle):
+ self.assertEquals(expected_sle[i][0], sle.item_code)
+ self.assertEquals(expected_sle[i][1], sle.warehouse)
+ self.assertEquals(expected_sle[i][2], sle.actual_qty)
+
+ def check_gl_entries(self, voucher_type, voucher_no, expected_gl_entries):
+ # check gl entries
+
+ gl_entries = webnotes.conn.sql("""select account, debit, credit
+ from `tabGL Entry` where voucher_type=%s and voucher_no=%s
+ order by account asc, debit asc""", (voucher_type, voucher_no), as_dict=1)
+ self.assertTrue(gl_entries)
+ for i, gle in enumerate(gl_entries):
+ self.assertEquals(expected_gl_entries[i][0], gle.account)
+ self.assertEquals(expected_gl_entries[i][1], gle.debit)
+ self.assertEquals(expected_gl_entries[i][2], gle.credit)
test_records = [
[
@@ -29,7 +166,8 @@ test_records = [
"doctype": "Stock Entry",
"posting_date": "2013-01-25",
"posting_time": "17:14:24",
- "purpose": "Material Receipt"
+ "purpose": "Material Receipt",
+ "fiscal_year": "_Test Fiscal Year 2013",
},
{
"conversion_factor": 1.0,
@@ -50,7 +188,8 @@ test_records = [
"doctype": "Stock Entry",
"posting_date": "2013-01-25",
"posting_time": "17:15",
- "purpose": "Material Issue"
+ "purpose": "Material Issue",
+ "fiscal_year": "_Test Fiscal Year 2013",
},
{
"conversion_factor": 1.0,
@@ -71,12 +210,13 @@ test_records = [
"doctype": "Stock Entry",
"posting_date": "2013-01-25",
"posting_time": "17:14:24",
- "purpose": "Material Transfer"
+ "purpose": "Material Transfer",
+ "fiscal_year": "_Test Fiscal Year 2013",
},
{
"conversion_factor": 1.0,
"doctype": "Stock Entry Detail",
- "item_code": "_Test Item Home Desktop 100",
+ "item_code": "_Test Item",
"parentfield": "mtn_details",
"incoming_rate": 100,
"qty": 45.0,
@@ -85,19 +225,6 @@ test_records = [
"uom": "_Test UOM",
"s_warehouse": "_Test Warehouse",
"t_warehouse": "_Test Warehouse 1",
- },
- {
- "conversion_factor": 1.0,
- "doctype": "Stock Entry Detail",
- "item_code": "_Test Item Home Desktop 100",
- "parentfield": "mtn_details",
- "qty": 45.0,
- "incoming_rate": 100,
- "stock_uom": "_Test UOM",
- "transfer_qty": 45.0,
- "uom": "_Test UOM",
- "s_warehouse": "_Test Warehouse",
- "t_warehouse": "_Test Warehouse 1",
}
]
]
\ No newline at end of file
diff --git a/stock/doctype/stock_ledger/stock_ledger.py b/stock/doctype/stock_ledger/stock_ledger.py
index 05fc0e0642b..5dff992ae40 100644
--- a/stock/doctype/stock_ledger/stock_ledger.py
+++ b/stock/doctype/stock_ledger/stock_ledger.py
@@ -17,7 +17,7 @@
from __future__ import unicode_literals
import webnotes
-from webnotes.utils import add_days, cstr, flt, nowdate, cint
+from webnotes.utils import add_days, cstr, flt, nowdate, cint, now
from webnotes.model.doc import Document
from webnotes.model.bean import getlist
from webnotes.model.code import get_obj
@@ -49,7 +49,7 @@ class DocType:
serial_nos = get_valid_serial_nos(d.serial_no)
for s in serial_nos:
s = s.strip()
- sr_war = sql("select warehouse,name from `tabSerial No` where name = '%s'" % (s))
+ sr_war = webnotes.conn.sql("select warehouse,name from `tabSerial No` where name = '%s'" % (s))
if not sr_war:
msgprint("Serial No %s does not exists"%s, raise_exception = 1)
elif not sr_war[0][0]:
@@ -81,7 +81,7 @@ class DocType:
def set_pur_serial_no_values(self, obj, serial_no, d, s, new_rec, rejected=None):
- item_details = sql("""select item_group, warranty_period
+ item_details = webnotes.conn.sql("""select item_group, warranty_period
from `tabItem` where name = '%s' and (ifnull(end_of_life,'')='' or
end_of_life = '0000-00-00' or end_of_life > now()) """ %(d.item_code), as_dict=1)
@@ -112,7 +112,7 @@ class DocType:
def update_serial_purchase_details(self, obj, d, serial_no, is_submit, purpose = '', rejected=None):
- exists = sql("select name, status, docstatus from `tabSerial No` where name = '%s'" % (serial_no))
+ exists = webnotes.conn.sql("select name, status, docstatus from `tabSerial No` where name = '%s'" % (serial_no))
if is_submit:
if exists and exists[0][2] != 2 and purpose not in ['Material Transfer', 'Sales Return']:
msgprint("Serial No: %s already %s" % (serial_no, exists and exists[0][1]), raise_exception = 1)
@@ -126,15 +126,15 @@ class DocType:
if exists and exists[0][1] == 'Delivered' and exists[0][2] != 2:
msgprint("Serial No: %s is already delivered, you can not cancel the document." % serial_no, raise_exception=1)
elif purpose == 'Material Transfer':
- sql("update `tabSerial No` set status = 'In Store', purchase_document_type = '', purchase_document_no = '', warehouse = '%s' where name = '%s'" % (d.s_warehouse, serial_no))
+ webnotes.conn.sql("update `tabSerial No` set status = 'In Store', purchase_document_type = '', purchase_document_no = '', warehouse = '%s' where name = '%s'" % (d.s_warehouse, serial_no))
elif purpose == 'Sales Return':
- sql("update `tabSerial No` set status = 'Delivered', purchase_document_type = '', purchase_document_no = '' where name = '%s'" % serial_no)
+ webnotes.conn.sql("update `tabSerial No` set status = 'Delivered', purchase_document_type = '', purchase_document_no = '' where name = '%s'" % serial_no)
else:
- sql("update `tabSerial No` set docstatus = 2, status = 'Not in Use', purchase_document_type = '', purchase_document_no = '', purchase_date = null, purchase_rate = 0, supplier = null, supplier_name = '', supplier_address = '', warehouse = '' where name = '%s'" % serial_no)
+ webnotes.conn.sql("update `tabSerial No` set docstatus = 2, status = 'Not in Use', purchase_document_type = '', purchase_document_no = '', purchase_date = null, purchase_rate = 0, supplier = null, supplier_name = '', supplier_address = '', warehouse = '' where name = '%s'" % serial_no)
def check_serial_no_exists(self, serial_no, item_code):
- chk = sql("select name, status, docstatus, item_code from `tabSerial No` where name = %s", (serial_no), as_dict=1)
+ chk = webnotes.conn.sql("select name, status, docstatus, item_code from `tabSerial No` where name = %s", (serial_no), as_dict=1)
if not chk:
msgprint("Serial No: %s does not exists in the system" % serial_no, raise_exception=1)
elif chk and chk[0]['item_code'] != item_code:
@@ -169,7 +169,7 @@ class DocType:
self.check_serial_no_exists(serial_no, d.item_code)
self.set_delivery_serial_no_values(obj, serial_no)
else:
- sql("update `tabSerial No` set docstatus = 0, status = 'In Store', delivery_document_type = '', delivery_document_no = '', delivery_date = null, customer = null, customer_name = '', delivery_address = '', territory = null where name = '%s'" % (serial_no))
+ webnotes.conn.sql("update `tabSerial No` set docstatus = 0, status = 'In Store', delivery_document_type = '', delivery_document_no = '', delivery_date = null, customer = null, customer_name = '', delivery_address = '', territory = null where name = '%s'" % (serial_no))
def update_serial_record(self, obj, fname, is_submit = 1, is_incoming = 0):
@@ -202,8 +202,10 @@ class DocType:
if v.get('is_cancelled') == 'Yes':
v['actual_qty'] = -flt(v['actual_qty'])
# cancel matching entry
- sql("update `tabStock Ledger Entry` set is_cancelled='Yes' where voucher_no=%s \
- and voucher_type=%s", (v['voucher_no'], v['voucher_type']))
+ webnotes.conn.sql("""update `tabStock Ledger Entry` set is_cancelled='Yes',
+ modified=%s, modified_by=%s
+ where voucher_no=%s and voucher_type=%s""",
+ (now(), webnotes.session.user, v['voucher_no'], v['voucher_type']))
if v.get("actual_qty"):
sle_id = self.make_entry(v)
@@ -230,5 +232,5 @@ class DocType:
"""
Repost everything!
"""
- for wh in sql("select name from tabWarehouse"):
+ for wh in webnotes.conn.sql("select name from tabWarehouse"):
get_obj('Warehouse', wh[0]).repost_stock()
diff --git a/stock/doctype/warehouse/warehouse.txt b/stock/doctype/warehouse/warehouse.txt
index d0dd73c0869..d08b3ccff34 100644
--- a/stock/doctype/warehouse/warehouse.txt
+++ b/stock/doctype/warehouse/warehouse.txt
@@ -1,8 +1,8 @@
[
{
- "creation": "2013-01-10 16:34:30",
+ "creation": "2013-03-07 18:50:32",
"docstatus": 0,
- "modified": "2013-02-04 11:35:53",
+ "modified": "2013-03-11 17:58:45",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -21,7 +21,8 @@
"name": "__common__",
"parent": "Warehouse",
"parentfield": "fields",
- "parenttype": "DocType"
+ "parenttype": "DocType",
+ "read_only": 0
},
{
"doctype": "DocPerm",
@@ -190,7 +191,7 @@
"permlevel": 0
},
{
- "description": "This feature is for merging duplicate warehouses. It will replace all the links of this warehouse by \"Merge With\" warehouse. After merging you can delete this warehouse, as stock level for this warehouse will be zero.",
+ "description": "This feature is for merging duplicate warehouses. It will replace all the links of this warehouse by \"Merge Into\" warehouse. After merging you can delete this warehouse, as stock level for this warehouse will be zero.",
"doctype": "DocField",
"fieldname": "merge_warehouses_section",
"fieldtype": "Section Break",
@@ -201,7 +202,7 @@
"doctype": "DocField",
"fieldname": "merge_with",
"fieldtype": "Link",
- "label": "Merge With",
+ "label": "Merge Into",
"options": "Warehouse",
"permlevel": 2
},
@@ -221,24 +222,6 @@
"role": "Material Master Manager",
"write": 1
},
- {
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "doctype": "DocPerm",
- "permlevel": 0,
- "role": "Material User",
- "write": 0
- },
- {
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "doctype": "DocPerm",
- "permlevel": 2,
- "role": "Material User",
- "write": 0
- },
{
"cancel": 1,
"create": 1,
@@ -248,6 +231,26 @@
"write": 1
},
{
+ "amend": 0,
+ "cancel": 0,
+ "create": 0,
+ "doctype": "DocPerm",
+ "permlevel": 0,
+ "role": "Material Manager",
+ "write": 0
+ },
+ {
+ "amend": 0,
+ "cancel": 0,
+ "create": 0,
+ "doctype": "DocPerm",
+ "permlevel": 0,
+ "role": "Material User",
+ "write": 0
+ },
+ {
+ "amend": 0,
+ "cancel": 0,
"create": 0,
"doctype": "DocPerm",
"permlevel": 2,
diff --git a/stock/page/stock_balance/stock_balance.js b/stock/page/stock_balance/stock_balance.js
index 9494f0dde6f..47a3344b296 100644
--- a/stock/page/stock_balance/stock_balance.js
+++ b/stock/page/stock_balance/stock_balance.js
@@ -99,6 +99,7 @@ erpnext.StockBalance = erpnext.StockAnalytics.extend({
var data = wn.report_dump.data["Stock Ledger Entry"];
this.item_warehouse = {};
+ this.serialized_buying_rates = this.get_serialized_buying_rates();
for(var i=0, j=data.length; i i+1:
if (sle.voucher_detail_no == item_row) or \
(sle.item_code == item_code and sle.warehouse == warehouse and \
abs(flt(sle.qty)) == qty):
- buying_amount = flt(stock_ledger_entries[i+1].stock_value) - flt(sle.stock_value)
-
+ buying_amount = flt(stock_ledger_entries[i+1].stock_value) - \
+ flt(sle.stock_value)
return buying_amount
-
return 0.0
def get_sales_bom():
item_sales_bom = {}
+ # for r in webnotes.conn.sql("""select parent_item, item_code, qty, warehouse, voucher_detail_no
+ # from `tabDelivery Note Packing Item` where docstatus = 1""", as_dict=1):
for r in webnotes.conn.sql("""select parent, item_code, qty from `tabSales BOM Item`""",
as_dict=1):
item_sales_bom.setdefault(r.parent, []).append(r)
diff --git a/utilities/cleanup_data.py b/utilities/cleanup_data.py
index a9cc5c340e8..ed04a94bfaa 100644
--- a/utilities/cleanup_data.py
+++ b/utilities/cleanup_data.py
@@ -20,16 +20,14 @@ import webnotes
def delete_transactions():
print "Deleting transactions..."
- trans = ['Timesheet','Task','Support Ticket','Stock Reconciliation', 'Stock Ledger Entry', \
- 'Stock Entry','Sales Order','Salary Slip','Sales Invoice','Quotation', 'Quality Inspection', \
- 'Purchase Receipt','Purchase Order','Production Order', 'POS Setting','Period Closing Voucher', \
- 'Purchase Invoice','Maintenance Visit','Maintenance Schedule','Leave Application', \
- 'Leave Allocation', 'Lead', 'Journal Voucher', 'Installation Note','Material Request', \
- 'GL Entry','Expense Claim','Opportunity','Delivery Note','Customer Issue','Bin', \
- 'Authorization Rule','Attendance', 'C-Form', 'Form 16A', 'Lease Agreement', \
- 'Lease Installment', 'TDS Payment', 'TDS Return Acknowledgement', 'Appraisal', \
- 'Installation Note', 'Communication'
- ]
+ trans = ['Timesheet', 'Task', 'Support Ticket', 'Stock Reconciliation', 'Stock Ledger Entry',
+ 'Stock Entry', 'Sales Order', 'Salary Slip','Sales Invoice', 'Quotation',
+ 'Quality Inspection', 'Purchase Receipt', 'Purchase Order', 'Production Order',
+ 'POS Setting', 'Period Closing Voucher', 'Purchase Invoice', 'Maintenance Visit',
+ 'Maintenance Schedule', 'Leave Application', 'Leave Allocation', 'Lead', 'Journal Voucher',
+ 'Installation Note', 'Material Request', 'GL Entry', 'Expense Claim', 'Opportunity',
+ 'Delivery Note', 'Customer Issue', 'Bin', 'Authorization Rule', 'Attendance', 'C-Form',
+ 'Appraisal', 'Installation Note', 'Communication']
for d in trans:
for t in webnotes.conn.sql("select options from tabDocField where parent='%s' and fieldtype='Table'" % d):
webnotes.conn.sql("delete from `tab%s`" % (t))
@@ -41,55 +39,55 @@ def delete_transactions():
def delete_masters():
print "Deleting masters...."
masters = {
- 'Workstation':['Default Workstation'],
- 'Warehouse Type':['Default Warehouse Type', 'Fixed Asset', 'Rejected', 'Reserved',
+ 'Workstation': ['Default Workstation'],
+ 'Warehouse Type': ['Default Warehouse Type', 'Fixed Asset', 'Rejected', 'Reserved',
'Sample', 'Stores', 'WIP Warehouse'],
- 'Warehouse':['Default Warehouse'],
- 'UOM':['Kg', 'Mtr', 'Box', 'Ltr', 'Nos', 'Ft', 'Pair', 'Set'],
- 'Territory':['All Territories', 'Default Territory'],
- 'Terms and Conditions':'',
- 'Tag':'',
- 'Supplier Type':['Default Supplier Type'],
- 'Supplier':'',
- 'Serial No':'',
- 'Sales Person':['All Sales Persons'],
- 'Sales Partner':'',
- 'Sales BOM':'',
- 'Salary Structure':'',
- 'Purchase Taxes and Charges Master':'',
- 'Project':'',
- 'Print Heading':'',
- 'Price List':['Default Price List'],
- 'Sales Taxes and Charges Master':'',
- 'Letter Head':'',
- 'Leave Type':['Leave Without Pay', 'Privilege Leave', 'Casual Leave', 'PL', 'CL', 'LWP',
+ 'Warehouse': ['Default Warehouse'],
+ 'UOM': ['Kg', 'Mtr', 'Box', 'Ltr', 'Nos', 'Ft', 'Pair', 'Set'],
+ 'Territory': ['All Territories', 'Default Territory'],
+ 'Terms and Conditions': '',
+ 'Tag': '',
+ 'Supplier Type': ['Default Supplier Type'],
+ 'Supplier': '',
+ 'Serial No': '',
+ 'Sales Person': ['All Sales Persons'],
+ 'Sales Partner': '',
+ 'Sales BOM': '',
+ 'Salary Structure': '',
+ 'Purchase Taxes and Charges Master': '',
+ 'Project': '',
+ 'Print Heading': '',
+ 'Price List': ['Default Price List'],
+ 'Sales Taxes and Charges Master': '',
+ 'Letter Head': '',
+ 'Leave Type': ['Leave Without Pay', 'Privilege Leave', 'Casual Leave', 'PL', 'CL', 'LWP',
'Compensatory Off', 'Sick Leave'],
- 'Appraisal Template':'',
- 'Item Group':['All Item Groups', 'Default'],
- 'Item':'',
- 'Holiday List':'',
- 'Grade':'',
- 'Feed':'',
- 'Expense Claim Type':['Travel', 'Medical', 'Calls', 'Food', 'Others'],
- 'Event':'',
- 'Employment Type':'',
- 'Employee':'',
- 'Earning Type':['Basic', 'Conveyance', 'House Rent Allowance', 'Dearness Allowance',
+ 'Appraisal Template': '',
+ 'Item Group': ['All Item Groups', 'Default'],
+ 'Item': '',
+ 'Holiday List': '',
+ 'Grade': '',
+ 'Feed': '',
+ 'Expense Claim Type': ['Travel', 'Medical', 'Calls', 'Food', 'Others'],
+ 'Event': '',
+ 'Employment Type': '',
+ 'Employee': '',
+ 'Earning Type': ['Basic', 'Conveyance', 'House Rent Allowance', 'Dearness Allowance',
'Medical Allowance', 'Telephone'],
- 'Designation':'',
- 'Department':'',
- 'Deduction Type':['Income Tax', 'Professional Tax', 'Provident Fund', 'Leave Deduction'],
- 'Customer Group':['All Customer Groups', 'Default Customer Group'],
- 'Customer':'',
- 'Cost Center':'',
- 'Contact':'',
- 'Campaign':'',
- 'Budget Distribution':'',
- 'Brand':'',
- 'Branch':'',
- 'Batch':'',
- 'Appraisal':'',
- 'Account':'',
+ 'Designation': '',
+ 'Department': '',
+ 'Deduction Type': ['Income Tax', 'Professional Tax', 'Provident Fund', 'Leave Deduction'],
+ 'Customer Group': ['All Customer Groups', 'Default Customer Group'],
+ 'Customer': '',
+ 'Cost Center': '',
+ 'Contact': '',
+ 'Campaign': '',
+ 'Budget Distribution': '',
+ 'Brand': '',
+ 'Branch': '',
+ 'Batch': '',
+ 'Appraisal': '',
+ 'Account': '',
'BOM': ''
}
for d in masters.keys():
@@ -115,40 +113,40 @@ def reset_all_series():
def reset_transaction_series():
webnotes.conn.sql("""update tabSeries set current = 0 where name in
('JV', 'INV', 'BILL', 'SO', 'DN', 'PO', 'LEAD', 'ENQUIRY', 'ENQ', 'CI',
- 'IN', 'PS', 'IDT', 'QAI', 'QTN', 'STE', 'SQTN', 'SUP', 'TDSP', 'SR',
+ 'IN', 'PS', 'IDT', 'QAI', 'QTN', 'STE', 'SQTN', 'SUP', 'SR',
'POS', 'LAP', 'LAL', 'EXP')""")
print "Series updated"
def delete_main_masters():
- main_masters = ['Fiscal Year','Company', 'DefaultValue']
+ main_masters = ['Fiscal Year', 'Company', 'DefaultValue']
for d in main_masters:
for t in webnotes.conn.sql("select options from tabDocField where parent='%s' and fieldtype='Table'" % d):
webnotes.conn.sql("delete from `tab%s`" % (t))
webnotes.conn.sql("delete from `tab%s`" % (d))
print "Deleted " + d
-
-
def reset_global_defaults():
flds = {
- 'default_company': '',
- 'default_currency': '',
- 'current_fiscal_year': '',
+ 'default_company': None,
+ 'default_currency': None,
+ 'current_fiscal_year': None,
'date_format': 'dd-mm-yyyy',
- 'sms_sender_name': '',
+ 'sms_sender_name': None,
'default_item_group': 'Default',
'default_stock_uom': 'Nos',
'default_valuation_method': 'FIFO',
'default_warehouse_type': 'Default Warehouse Type',
- 'tolerance': '',
- 'acc_frozen_upto': '',
- 'bde_auth_role': '',
- 'credit_controller': '',
+ 'tolerance': None,
+ 'acc_frozen_upto': None,
+ 'bde_auth_role': None,
+ 'credit_controller': None,
'default_customer_group': 'Default Customer Group',
'default_territory': 'Default',
'default_price_list': 'Standard',
- 'default_supplier_type': 'Default Supplier Type'
+ 'default_supplier_type': 'Default Supplier Type',
+ 'hide_currency_symbol': None,
+ 'default_price_list_currency': None,
}
from webnotes.model.code import get_obj
diff --git a/website/css/website.css b/website/css/website.css
index 956f22e8bc5..dc5b9670b35 100644
--- a/website/css/website.css
+++ b/website/css/website.css
@@ -1,17 +1,12 @@
div.outer {
- -moz-box-shadow: 0px 0px 3px rgba(0,0,0,0.9);
- -webkit-box-shadow: 0px 0px 3px rgba(0,0,0,0.9);
- box-shadow: 0px 0px 3px rgba(0,0,0,0.9);
- background-color: #fff;
- border-radius: 5px;
- padding: 20px;
- margin: 30px -20px 10px -20px;
+ padding: 30px;
+ margin: 30px -30px 10px -30px;
min-height: 400px;
overflow: hidden;
}
.outer .navbar {
- margin: -20px -20px 10px -20px;
+ margin: -30px -30px 10px -30px;
}
footer {
@@ -24,6 +19,8 @@ footer {
border: 0px;
border-bottom: 1px solid #ddd;
border-radius: 0px;
+ padding-right: 30px;
+ padding-left: 30px;
}
p, li {
@@ -98,6 +95,18 @@ p, li {
width: 30px;
}
+.avatar-medium {
+ margin-right: 5px;
+ width: 48px;
+ height: 48px;
+ border-radius: 48px;
+ -moz-border-radius: 48px;
+ -webkit-border-radius: 48px;
+}
+.avatar-medium img {
+ width: 48px;
+}
+
.avatar-large {
margin-right: 10px;
width: 72px;
@@ -121,5 +130,3 @@ p, li {
.avatar-x-large img {
width: 100px;
}
-
-/* */
\ No newline at end of file
diff --git a/website/doctype/about_us_settings/about_us_settings.py b/website/doctype/about_us_settings/about_us_settings.py
index 6c404f16f82..e291aa85d00 100644
--- a/website/doctype/about_us_settings/about_us_settings.py
+++ b/website/doctype/about_us_settings/about_us_settings.py
@@ -7,16 +7,16 @@ from website.utils import url_for_website
class DocType:
def __init__(self, d, dl):
self.doc, self.doclist = d, dl
-
- def onload(self):
- """load employee"""
- emp_list = []
- for d in self.doclist.get({"doctype":"About Us Team Member"}):
- emp = webnotes.doc("Employee", d.employee)
- emp.image = url_for_website(emp.image)
- emp_list.append(emp)
- self.doclist += emp_list
-
+
def on_update(self):
from website.utils import clear_cache
- clear_cache("about")
\ No newline at end of file
+ clear_cache("about")
+
+def get_args():
+ obj = webnotes.get_obj("About Us Settings")
+ for d in obj.doclist.get({"doctype":"About Us Team Member"}):
+ if not "/" in d.image_link:
+ d.image_link = "files/" + d.image_link
+ return {
+ "obj": obj
+ }
\ No newline at end of file
diff --git a/website/doctype/about_us_settings/about_us_settings.txt b/website/doctype/about_us_settings/about_us_settings.txt
index a42d2f35119..b846d2bc6c2 100644
--- a/website/doctype/about_us_settings/about_us_settings.txt
+++ b/website/doctype/about_us_settings/about_us_settings.txt
@@ -1,12 +1,13 @@
[
{
- "creation": "2013-01-10 16:34:32",
+ "creation": "2013-03-07 15:53:15",
"docstatus": 0,
- "modified": "2013-01-22 14:12:16",
+ "modified": "2013-03-12 14:48:34",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
+ "allow_attach": 1,
"description": "Settings for the About Us Page",
"doctype": "DocType",
"document_type": "Master",
@@ -31,7 +32,7 @@
"parenttype": "DocType",
"permlevel": 0,
"read": 1,
- "report": 1,
+ "report": 0,
"role": "Website Manager",
"submit": 0,
"write": 1
@@ -45,7 +46,7 @@
"fieldname": "help",
"fieldtype": "HTML",
"label": "Help",
- "options": "Link for About Us Page is \"about.html\"
"
+ "options": "Link for About Us Page is \"/about\"
"
},
{
"description": "Introduce your company to the website visitor.",
@@ -101,6 +102,15 @@
"fieldtype": "Text Editor",
"label": "Footer"
},
+ {
+ "doctype": "DocField",
+ "fieldname": "file_list",
+ "fieldtype": "Text",
+ "hidden": 1,
+ "label": "File List",
+ "no_copy": 1,
+ "print_hide": 1
+ },
{
"doctype": "DocPerm"
}
diff --git a/website/doctype/about_us_team_member/about_us_team_member.txt b/website/doctype/about_us_team_member/about_us_team_member.txt
index ec77dd78b3a..b1bf6b306a3 100644
--- a/website/doctype/about_us_team_member/about_us_team_member.txt
+++ b/website/doctype/about_us_team_member/about_us_team_member.txt
@@ -1,8 +1,8 @@
[
{
- "creation": "2013-02-22 01:28:07",
+ "creation": "2013-03-07 11:55:11",
"docstatus": 0,
- "modified": "2013-03-07 07:03:18",
+ "modified": "2013-03-12 13:51:02",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -14,23 +14,38 @@
},
{
"doctype": "DocField",
- "fieldname": "employee",
- "fieldtype": "Link",
- "label": "Employee",
"name": "__common__",
- "options": "Employee",
"parent": "About Us Team Member",
"parentfield": "fields",
"parenttype": "DocType",
- "permlevel": 0,
- "print_width": "300px",
- "width": "300px"
+ "permlevel": 0
},
{
"doctype": "DocType",
"name": "About Us Team Member"
},
{
- "doctype": "DocField"
+ "doctype": "DocField",
+ "fieldname": "full_name",
+ "fieldtype": "Data",
+ "label": "Full Name",
+ "reqd": 1,
+ "width": "150px"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "image_link",
+ "fieldtype": "Select",
+ "label": "Image Link",
+ "options": "attach_files:",
+ "width": "150px"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "bio",
+ "fieldtype": "Small Text",
+ "label": "Bio",
+ "reqd": 1,
+ "width": "200px"
}
]
\ No newline at end of file
diff --git a/website/doctype/blog/__init__.py b/website/doctype/blog/__init__.py
deleted file mode 100644
index baffc488252..00000000000
--- a/website/doctype/blog/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/website/doctype/blog/locale/_messages_doc.json b/website/doctype/blog/locale/_messages_doc.json
deleted file mode 100644
index 90697bdf72b..00000000000
--- a/website/doctype/blog/locale/_messages_doc.json
+++ /dev/null
@@ -1,12 +0,0 @@
-[
- "Website",
- "Content",
- "Title",
- "Blog Intro",
- "Page Name",
- "Blog",
- "Email Sent",
- "File List",
- "Published",
- "Description for listing page, in plain text, only a couple of lines."
-]
\ No newline at end of file
diff --git a/website/doctype/blog/locale/ar-doc.json b/website/doctype/blog/locale/ar-doc.json
deleted file mode 100644
index 10ecf122d52..00000000000
--- a/website/doctype/blog/locale/ar-doc.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "Blog": "\u0628\u0644\u0648\u0642",
- "Content": "\u0645\u062d\u062a\u0648\u0649",
- "Email Sent": "\u0625\u0631\u0633\u0627\u0644 \u0627\u0644\u0628\u0631\u064a\u062f \u0627\u0644\u0625\u0644\u0643\u062a\u0631\u0648\u0646\u064a",
- "File List": "\u0645\u0644\u0641 \u0642\u0627\u0626\u0645\u0629",
- "Page Name": "\u0627\u0644\u0635\u0641\u062d\u0629 \u0627\u0633\u0645",
- "Published": "\u0646\u0634\u0631\u062a",
- "Title": "\u0644\u0642\u0628",
- "Website": "\u0627\u0644\u0645\u0648\u0642\u0639"
-}
\ No newline at end of file
diff --git a/website/doctype/blog/locale/de-doc.json b/website/doctype/blog/locale/de-doc.json
deleted file mode 100644
index a4f001348d2..00000000000
--- a/website/doctype/blog/locale/de-doc.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "Blog": "Blog",
- "Content": "Inhalt",
- "Email Sent": "E-Mail gesendet",
- "File List": "Dateiliste",
- "Page Name": "Page Name",
- "Published": "Ver\u00f6ffentlicht",
- "Title": "Titel",
- "Website": "Webseite"
-}
\ No newline at end of file
diff --git a/website/doctype/blog/locale/es-doc.json b/website/doctype/blog/locale/es-doc.json
deleted file mode 100644
index 727ca1257c9..00000000000
--- a/website/doctype/blog/locale/es-doc.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "Blog": "Blog",
- "Content": "Contenido",
- "Email Sent": "Correo electr\u00f3nico enviado",
- "File List": "Lista de archivos",
- "Page Name": "Nombre p\u00e1gina",
- "Published": "Publicado",
- "Title": "T\u00edtulo",
- "Website": "Sitio web"
-}
\ No newline at end of file
diff --git a/website/doctype/blog/locale/fr-doc.json b/website/doctype/blog/locale/fr-doc.json
deleted file mode 100644
index d30abca1d4f..00000000000
--- a/website/doctype/blog/locale/fr-doc.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "Blog": "Blog",
- "Content": "Teneur",
- "Email Sent": "Courriel a \u00e9t\u00e9 envoy\u00e9",
- "File List": "Liste des fichiers",
- "Page Name": "Nom de la page",
- "Published": "Publi\u00e9",
- "Title": "Titre",
- "Website": "Site Web"
-}
\ No newline at end of file
diff --git a/website/doctype/blog/locale/hi-doc.json b/website/doctype/blog/locale/hi-doc.json
deleted file mode 100644
index 5191c3a4ad2..00000000000
--- a/website/doctype/blog/locale/hi-doc.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "Blog": "\u092c\u094d\u0932\u0949\u0917",
- "Content": "\u0938\u093e\u092e\u0917\u094d\u0930\u0940",
- "Email Sent": "\u0908\u092e\u0947\u0932 \u092d\u0947\u091c\u093e \u0917\u092f\u093e",
- "File List": "\u092b\u093c\u093e\u0907\u0932 \u0938\u0942\u091a\u0940",
- "Page Name": "\u092a\u0947\u091c \u0915\u093e \u0928\u093e\u092e",
- "Published": "\u092a\u094d\u0930\u0915\u093e\u0936\u093f\u0924",
- "Title": "\u0936\u0940\u0930\u094d\u0937\u0915",
- "Website": "\u0935\u0947\u092c\u0938\u093e\u0907\u091f"
-}
\ No newline at end of file
diff --git a/website/doctype/blog/locale/hr-doc.json b/website/doctype/blog/locale/hr-doc.json
deleted file mode 100644
index b77e5aca35c..00000000000
--- a/website/doctype/blog/locale/hr-doc.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "Blog": "Blog",
- "Content": "Sadr\u017eaj",
- "Email Sent": "E-mail poslan",
- "File List": "Popis datoteka",
- "Page Name": "Stranica Ime",
- "Published": "Objavljen",
- "Title": "Naslov",
- "Website": "Website"
-}
\ No newline at end of file
diff --git a/website/doctype/blog/locale/nl-doc.json b/website/doctype/blog/locale/nl-doc.json
deleted file mode 100644
index 08aca3d44c7..00000000000
--- a/website/doctype/blog/locale/nl-doc.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "Blog": "Blog",
- "Content": "Inhoud",
- "Email Sent": "E-mail verzonden",
- "File List": "File List",
- "Page Name": "Page Name",
- "Published": "Gepubliceerd",
- "Title": "Titel",
- "Website": "Website"
-}
\ No newline at end of file
diff --git a/website/doctype/blog/locale/pt-BR-doc.json b/website/doctype/blog/locale/pt-BR-doc.json
deleted file mode 100644
index b30e539a058..00000000000
--- a/website/doctype/blog/locale/pt-BR-doc.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "Blog": "Blog",
- "Blog Intro": "Blog Intro",
- "Content": "Conte\u00fado",
- "Description for listing page, in plain text, only a couple of lines.": "Descri\u00e7\u00e3o p\u00e1gina de listagem, em texto simples, apenas um par de linhas.",
- "Email Sent": "E-mail enviado",
- "File List": "Lista de Arquivos",
- "Page Name": "Nome da P\u00e1gina",
- "Published": "Publicado",
- "Title": "T\u00edtulo",
- "Website": "Site"
-}
\ No newline at end of file
diff --git a/website/doctype/blog/locale/pt-doc.json b/website/doctype/blog/locale/pt-doc.json
deleted file mode 100644
index 39bc7d4009e..00000000000
--- a/website/doctype/blog/locale/pt-doc.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "Blog": "Blog",
- "Content": "Conte\u00fado",
- "Email Sent": "E-mail enviado",
- "File List": "Lista de Arquivos",
- "Page Name": "Nome da P\u00e1gina",
- "Published": "Publicado",
- "Title": "T\u00edtulo",
- "Website": "Site"
-}
\ No newline at end of file
diff --git a/website/doctype/blog/locale/sr-doc.json b/website/doctype/blog/locale/sr-doc.json
deleted file mode 100644
index 2b67eecdfe9..00000000000
--- a/website/doctype/blog/locale/sr-doc.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "Blog": "\u0411\u043b\u043e\u0433",
- "Content": "\u0421\u0430\u0434\u0440\u0436\u0438\u043d\u0430",
- "Email Sent": "\u0415\u043c\u0430\u0438\u043b \u0421\u0435\u043d\u0442",
- "File List": "\u0424\u0438\u043b\u0435 \u041b\u0438\u0441\u0442",
- "Page Name": "\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0418\u043c\u0435",
- "Published": "\u041e\u0431\u0458\u0430\u0432\u0459\u0435\u043d",
- "Title": "\u041d\u0430\u0441\u043b\u043e\u0432",
- "Website": "\u0412\u0435\u0431\u0441\u0430\u0458\u0442"
-}
\ No newline at end of file
diff --git a/website/doctype/blog/locale/ta-doc.json b/website/doctype/blog/locale/ta-doc.json
deleted file mode 100644
index c34c1926bbe..00000000000
--- a/website/doctype/blog/locale/ta-doc.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "Blog": "\u0bb5\u0bb2\u0bc8\u0baa\u0bcd\u0baa\u0ba4\u0bbf\u0bb5\u0bc1",
- "Content": "\u0b89\u0bb3\u0bcd\u0bb3\u0b9f\u0b95\u0bcd\u0b95\u0bae\u0bcd",
- "Email Sent": "\u0bae\u0bbf\u0ba9\u0bcd\u0ba9\u0b9e\u0bcd\u0b9a\u0bb2\u0bcd \u0b85\u0ba9\u0bc1\u0baa\u0bcd\u0baa\u0baa\u0bcd\u0baa\u0b9f\u0bcd\u0b9f\u0ba4\u0bc1",
- "File List": "\u0b95\u0bc7\u0bbe\u0baa\u0bcd\u0baa\u0bc1 \u0baa\u0b9f\u0bcd\u0b9f\u0bbf\u0baf\u0bb2\u0bcd",
- "Page Name": "\u0baa\u0b95\u0bcd\u0b95\u0bae\u0bcd \u0baa\u0bc6\u0baf\u0bb0\u0bcd",
- "Published": "\u0bb5\u0bc6\u0bb3\u0bbf\u0baf\u0bbf\u0b9f\u0baa\u0bcd\u0baa\u0b9f\u0bcd\u0b9f",
- "Title": "\u0ba4\u0bb2\u0bc8\u0baa\u0bcd\u0baa\u0bc1",
- "Website": "\u0b87\u0ba3\u0bc8\u0baf\u0ba4\u0bb3\u0bae\u0bcd"
-}
\ No newline at end of file
diff --git a/website/doctype/blog/locale/th-doc.json b/website/doctype/blog/locale/th-doc.json
deleted file mode 100644
index e043a41d7a9..00000000000
--- a/website/doctype/blog/locale/th-doc.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "Blog": "\u0e1a\u0e25\u0e47\u0e2d\u0e01",
- "Content": "\u0e40\u0e19\u0e37\u0e49\u0e2d\u0e2b\u0e32",
- "Email Sent": "\u0e2d\u0e35\u0e40\u0e21\u0e25\u0e17\u0e35\u0e48\u0e2a\u0e48\u0e07",
- "File List": "\u0e23\u0e32\u0e22\u0e0a\u0e37\u0e48\u0e2d\u0e44\u0e1f\u0e25\u0e4c",
- "Page Name": "\u0e0a\u0e37\u0e48\u0e2d\u0e40\u0e1e\u0e08",
- "Published": "\u0e40\u0e1c\u0e22\u0e41\u0e1e\u0e23\u0e48",
- "Title": "\u0e0a\u0e37\u0e48\u0e2d\u0e40\u0e23\u0e37\u0e48\u0e2d\u0e07",
- "Website": "\u0e40\u0e27\u0e47\u0e1a\u0e44\u0e0b\u0e15\u0e4c"
-}
\ No newline at end of file
diff --git a/website/doctype/blog_category/__init__.py b/website/doctype/blog_category/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/website/doctype/blog_category/blog_category.py b/website/doctype/blog_category/blog_category.py
new file mode 100644
index 00000000000..c8c369c4c0d
--- /dev/null
+++ b/website/doctype/blog_category/blog_category.py
@@ -0,0 +1,14 @@
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import webnotes
+
+class DocType:
+ def __init__(self, d, dl):
+ self.doc, self.doclist = d, dl
+
+ def on_update(self):
+ # for blog footer
+ from website.utils import clear_cache
+ clear_cache()
+
\ No newline at end of file
diff --git a/website/doctype/blog_category/blog_category.txt b/website/doctype/blog_category/blog_category.txt
new file mode 100644
index 00000000000..cf8cad66bf7
--- /dev/null
+++ b/website/doctype/blog_category/blog_category.txt
@@ -0,0 +1,51 @@
+[
+ {
+ "creation": "2013-03-08 09:41:11",
+ "docstatus": 0,
+ "modified": "2013-03-08 09:41:11",
+ "modified_by": "Administrator",
+ "owner": "Administrator"
+ },
+ {
+ "autoname": "field:category_name",
+ "doctype": "DocType",
+ "document_type": "Master",
+ "module": "Website",
+ "name": "__common__"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "category_name",
+ "fieldtype": "Data",
+ "label": "Category Name",
+ "name": "__common__",
+ "parent": "Blog Category",
+ "parentfield": "fields",
+ "parenttype": "DocType",
+ "permlevel": 0,
+ "reqd": 1
+ },
+ {
+ "cancel": 1,
+ "create": 1,
+ "doctype": "DocPerm",
+ "name": "__common__",
+ "parent": "Blog Category",
+ "parentfield": "permissions",
+ "parenttype": "DocType",
+ "permlevel": 0,
+ "read": 1,
+ "role": "Website Manager",
+ "write": 1
+ },
+ {
+ "doctype": "DocType",
+ "name": "Blog Category"
+ },
+ {
+ "doctype": "DocField"
+ },
+ {
+ "doctype": "DocPerm"
+ }
+]
\ No newline at end of file
diff --git a/website/doctype/blog_post/__init__.py b/website/doctype/blog_post/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/website/doctype/blog/blog.js b/website/doctype/blog_post/blog_post.js
similarity index 100%
rename from website/doctype/blog/blog.js
rename to website/doctype/blog_post/blog_post.js
diff --git a/website/doctype/blog/blog.py b/website/doctype/blog_post/blog_post.py
similarity index 67%
rename from website/doctype/blog/blog.py
rename to website/doctype/blog_post/blog_post.py
index cfc0ca643e9..ff6cc9931e4 100644
--- a/website/doctype/blog/blog.py
+++ b/website/doctype/blog_post/blog_post.py
@@ -18,6 +18,7 @@ from __future__ import unicode_literals
import webnotes
import website.utils
+from webnotes import _
class DocType:
def __init__(self, d, dl):
@@ -27,9 +28,18 @@ class DocType:
from website.utils import page_name
self.doc.name = page_name(self.doc.title)
+ def validate(self):
+ if self.doc.blog_intro:
+ self.doc.blog_intro = self.doc.blog_intro[:140]
+
+ # update posts
+ webnotes.conn.sql("""update tabBlogger set posts=(select count(*) from `tabBlog Post`
+ where ifnull(blogger,'')=tabBlogger.name)
+ where name=%s""", self.doc.blogger)
+
def on_update(self):
- from website.utils import update_page_name
- update_page_name(self.doc, self.doc.title)
+ website.utils.update_page_name(self.doc, self.doc.title)
+ website.utils.delete_page_cache("writers")
def send_emails(self):
"""send emails to subscribers"""
@@ -40,8 +50,8 @@ class DocType:
import webnotes.utils
# get leads that are subscribed to the blog
- recipients = [e[0] for e in webnotes.conn.sql("""select distinct email_id from tabLead where
- ifnull(blog_subscriber,0)=1""")]
+ recipients = [e[0] for e in webnotes.conn.sql("""select distinct email_id from
+ tabLead where ifnull(blog_subscriber,0)=1""")]
# make heading as link
content = '\n\n%s' % (webnotes.utils.get_request_site_address(),
@@ -64,12 +74,28 @@ class DocType:
# temp fields
from webnotes.utils import global_date_format, get_fullname
self.doc.full_name = get_fullname(self.doc.owner)
- self.doc.updated = global_date_format(self.doc.creation)
+ self.doc.updated = global_date_format(self.doc.published_on)
self.doc.content_html = self.doc.content
+ if self.doc.blogger:
+ self.doc.blogger_info = webnotes.doc("Blogger", self.doc.blogger).fields
+ if self.doc.blogger_info.avatar and not "/" in self.doc.blogger_info.avatar:
+ self.doc.blogger_info.avatar = "files/" + self.doc.blogger_info.avatar
+
+ self.doc.description = self.doc.blog_intro or self.doc.content[:140]
+
+ self.doc.categories = webnotes.conn.sql_list("select name from `tabBlog Category` order by name")
+
+ self.doc.texts = {
+ "comments": _("Comments"),
+ "first_comment": _("Be the first one to comment"),
+ "add_comment": _("Add Comment"),
+ "submit": _("Submit"),
+ "all_posts_by": _("All posts by"),
+ }
comment_list = webnotes.conn.sql("""\
select comment, comment_by_fullname, creation
- from `tabComment` where comment_doctype="Blog"
+ from `tabComment` where comment_doctype="Blog Post"
and comment_docname=%s order by creation""", self.doc.name, as_dict=1)
self.doc.comment_list = comment_list or []
diff --git a/website/doctype/blog/blog.txt b/website/doctype/blog_post/blog_post.txt
similarity index 66%
rename from website/doctype/blog/blog.txt
rename to website/doctype/blog_post/blog_post.txt
index af9606a71b2..480bca49243 100644
--- a/website/doctype/blog/blog.txt
+++ b/website/doctype/blog_post/blog_post.txt
@@ -1,13 +1,14 @@
[
{
- "creation": "2013-01-25 11:35:09",
+ "creation": "2013-03-08 11:36:50",
"docstatus": 0,
- "modified": "2013-02-21 16:54:04",
+ "modified": "2013-03-11 15:23:21",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"allow_attach": 1,
+ "allow_import": 1,
"doctype": "DocType",
"max_attachments": 5,
"module": "Website",
@@ -16,7 +17,7 @@
{
"doctype": "DocField",
"name": "__common__",
- "parent": "Blog",
+ "parent": "Blog Post",
"parentfield": "fields",
"parenttype": "DocType",
"permlevel": 0
@@ -24,7 +25,7 @@
{
"doctype": "DocPerm",
"name": "__common__",
- "parent": "Blog",
+ "parent": "Blog Post",
"parentfield": "permissions",
"parenttype": "DocType",
"permlevel": 0,
@@ -34,7 +35,7 @@
},
{
"doctype": "DocType",
- "name": "Blog"
+ "name": "Blog Post"
},
{
"doctype": "DocField",
@@ -50,18 +51,50 @@
"label": "Published"
},
{
- "description": "Description for listing page, in plain text, only a couple of lines.",
+ "doctype": "DocField",
+ "fieldname": "published_on",
+ "fieldtype": "Date",
+ "label": "Published On"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "column_break_3",
+ "fieldtype": "Column Break"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "blogger",
+ "fieldtype": "Link",
+ "label": "Blogger",
+ "options": "Blogger",
+ "reqd": 1
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "blog_category",
+ "fieldtype": "Link",
+ "label": "Blog Category",
+ "options": "Blog Category"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "section_break_5",
+ "fieldtype": "Section Break"
+ },
+ {
+ "description": "Description for listing page, in plain text, only a couple of lines. (max 140 characters)",
"doctype": "DocField",
"fieldname": "blog_intro",
"fieldtype": "Small Text",
- "label": "Blog Intro"
+ "label": "Blog Intro",
+ "reqd": 1
},
{
"doctype": "DocField",
"fieldname": "content",
"fieldtype": "Text Editor",
"label": "Content",
- "reqd": 0
+ "reqd": 1
},
{
"doctype": "DocField",
diff --git a/website/doctype/blog_settings/__init__.py b/website/doctype/blog_settings/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/website/doctype/blog_settings/blog_settings.py b/website/doctype/blog_settings/blog_settings.py
new file mode 100644
index 00000000000..928aa9ff9f2
--- /dev/null
+++ b/website/doctype/blog_settings/blog_settings.py
@@ -0,0 +1,8 @@
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import webnotes
+
+class DocType:
+ def __init__(self, d, dl):
+ self.doc, self.doclist = d, dl
\ No newline at end of file
diff --git a/website/doctype/blog_settings/blog_settings.txt b/website/doctype/blog_settings/blog_settings.txt
new file mode 100644
index 00000000000..09740eb78f8
--- /dev/null
+++ b/website/doctype/blog_settings/blog_settings.txt
@@ -0,0 +1,61 @@
+[
+ {
+ "creation": "2013-03-11 17:48:16",
+ "docstatus": 0,
+ "modified": "2013-03-11 17:48:16",
+ "modified_by": "Administrator",
+ "owner": "Administrator"
+ },
+ {
+ "description": "Blog Settings",
+ "doctype": "DocType",
+ "issingle": 1,
+ "module": "Website",
+ "name": "__common__"
+ },
+ {
+ "doctype": "DocField",
+ "name": "__common__",
+ "parent": "Blog Settings",
+ "parentfield": "fields",
+ "parenttype": "DocType",
+ "permlevel": 0
+ },
+ {
+ "create": 1,
+ "doctype": "DocPerm",
+ "name": "__common__",
+ "parent": "Blog Settings",
+ "parentfield": "permissions",
+ "parenttype": "DocType",
+ "permlevel": 0,
+ "read": 1,
+ "role": "Website Manager",
+ "write": 1
+ },
+ {
+ "doctype": "DocType",
+ "name": "Blog Settings"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "blog_title",
+ "fieldtype": "Data",
+ "label": "Blog Title"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "blog_introduction",
+ "fieldtype": "Small Text",
+ "label": "Blog Introduction"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "writers_introduction",
+ "fieldtype": "Small Text",
+ "label": "Writers Introduction"
+ },
+ {
+ "doctype": "DocPerm"
+ }
+]
\ No newline at end of file
diff --git a/website/doctype/blogger/__init__.py b/website/doctype/blogger/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/website/doctype/blogger/blogger.py b/website/doctype/blogger/blogger.py
new file mode 100644
index 00000000000..a16867dfc10
--- /dev/null
+++ b/website/doctype/blogger/blogger.py
@@ -0,0 +1,22 @@
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import webnotes
+
+class DocType:
+ def __init__(self, d, dl):
+ self.doc, self.doclist = d, dl
+
+ def on_update(self):
+ "if profile is set, then update all older blogs"
+
+ from website.helpers.blog import clear_blog_cache
+ clear_blog_cache()
+
+ if self.doc.profile:
+ for blog in webnotes.conn.sql_list("""select name from `tabBlog Post` where owner=%s
+ and ifnull(blogger,'')=''""", self.doc.profile):
+ b = webnotes.bean("Blog Post", blog)
+ b.doc.blogger = self.doc.name
+ b.save()
+
diff --git a/website/doctype/blogger/blogger.txt b/website/doctype/blogger/blogger.txt
new file mode 100644
index 00000000000..7f741c523c8
--- /dev/null
+++ b/website/doctype/blogger/blogger.txt
@@ -0,0 +1,102 @@
+[
+ {
+ "creation": "2013-03-08 11:36:52",
+ "docstatus": 0,
+ "modified": "2013-03-11 14:00:37",
+ "modified_by": "Administrator",
+ "owner": "Administrator"
+ },
+ {
+ "allow_attach": 1,
+ "autoname": "field:short_name",
+ "description": "Profile of a Blogger",
+ "doctype": "DocType",
+ "document_type": "Master",
+ "max_attachments": 1,
+ "module": "Website",
+ "name": "__common__"
+ },
+ {
+ "doctype": "DocField",
+ "name": "__common__",
+ "parent": "Blogger",
+ "parentfield": "fields",
+ "parenttype": "DocType",
+ "permlevel": 0
+ },
+ {
+ "doctype": "DocPerm",
+ "name": "__common__",
+ "parent": "Blogger",
+ "parentfield": "permissions",
+ "parenttype": "DocType",
+ "permlevel": 0,
+ "read": 1,
+ "write": 1
+ },
+ {
+ "doctype": "DocType",
+ "name": "Blogger"
+ },
+ {
+ "description": "Will be used in url (usually first name).",
+ "doctype": "DocField",
+ "fieldname": "short_name",
+ "fieldtype": "Data",
+ "label": "Short Name",
+ "reqd": 1
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "full_name",
+ "fieldtype": "Data",
+ "label": "Full Name",
+ "reqd": 1
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "profile",
+ "fieldtype": "Link",
+ "label": "Profile",
+ "options": "Profile"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "bio",
+ "fieldtype": "Small Text",
+ "label": "Bio"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "avatar",
+ "fieldtype": "Select",
+ "label": "Avatar",
+ "options": "attach_files:"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "posts",
+ "fieldtype": "Int",
+ "label": "Posts",
+ "read_only": 1
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "file_list",
+ "fieldtype": "Text",
+ "hidden": 1,
+ "label": "File List",
+ "no_copy": 1,
+ "print_hide": 1
+ },
+ {
+ "create": 1,
+ "doctype": "DocPerm",
+ "role": "Website Manager"
+ },
+ {
+ "doctype": "DocPerm",
+ "match": "owner:profile",
+ "role": "Blogger"
+ }
+]
\ No newline at end of file
diff --git a/website/doctype/contact_us_settings/contact_us_settings.txt b/website/doctype/contact_us_settings/contact_us_settings.txt
index 1bc7b057135..ef2da02af71 100644
--- a/website/doctype/contact_us_settings/contact_us_settings.txt
+++ b/website/doctype/contact_us_settings/contact_us_settings.txt
@@ -1,8 +1,8 @@
[
{
- "creation": "2012-12-27 19:04:50",
+ "creation": "2013-02-21 20:12:42",
"docstatus": 0,
- "modified": "2013-02-21 16:49:33",
+ "modified": "2013-03-12 14:49:01",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -44,7 +44,7 @@
"fieldname": "help",
"fieldtype": "HTML",
"label": "Help",
- "options": "Link for Contact Page is \"contact.html\"
"
+ "options": "Link for Contact Page is \"/contact\"
"
},
{
"description": "Address to be displayed on the Contact Page",
diff --git a/website/doctype/style_settings/custom_template.css b/website/doctype/style_settings/custom_template.css
index 9009bbe18a7..712c748cb83 100644
--- a/website/doctype/style_settings/custom_template.css
+++ b/website/doctype/style_settings/custom_template.css
@@ -1,3 +1,7 @@
+{% if doc.at_import %}
+{{ doc.at_import }}
+{% endif %}
+
body {
{% if doc.background_image %}
background: url("../files/{{ doc.background_image }}") repeat;
@@ -7,22 +11,232 @@ body {
{% else %}
background-color: #edede7;
{% endif %}
-{% if doc.font %}
- font-family: '{{ doc.font }}', Verdana, Sans !important;
-{% endif %}
-{% if doc.font_size %}
- font-size: {{ doc.font_size }} !important;
+{% if doc.font or doc.google_web_font_for_text %}
+ font-family: '{{ doc.google_web_font_for_text or doc.font }}', 'Helvetica Neue', Arial, Sans !important;
{% endif %}
+ {% if doc.font_size %}font-size: {{ doc.font_size }} !important;{% endif %}
+ {% if doc.page_text %}color: #{{ doc.page_text }};{% endif %}
}
+{% if doc.page_links %}a, a:hover {
+ color: #{{ doc.page_links }};
+}{% endif %}
+
{% if doc.font_size %}
.small {
font-size: {{ doc.small_font_size }} !important;
}
{% endif %}
-{% if doc.heading_font %}
-h1, h2, h3, h4, h5 {
- font-family: '{{ doc.heading_font}}', Arial, 'Helvetica Neue' !important;
-}
+div.outer {
+ background-color: #{{ doc.page_background or "fffffff" }};
+}
+
+{% if doc.google_web_font_for_heading or doc.heading_font %}h1, h2, h3, h4, h5 {
+ font-family: '{{ doc.google_web_font_for_heading or doc.heading_font }}', 'Helvetica Neue', Arial !important;
+}{% endif %}
+
+{% if doc.heading_text_style %}h1, h2, h3, h4, h5 {
+ text-transform: {{ doc.heading_text_style }};
+}{% endif %}
+
+{% if doc.page_headings %}h1, h2, h3, h4, h5 {
+ color: #{{ doc.page_headings }};
+}{% endif %}
+
+{% if doc.page_border %}
+/* Page Border*/
+div.outer {
+ box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
+ -webkibox-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
+}
+{% else %}
+{% if doc.background_color == doc.page_background %}
+div.web-footer {
+ border-top: 1px solid #{{ get_hex_shade(doc.page_background or "ffffff", 15) }};
+ padding-top: 10px;
+}
{% endif %}
+{% endif %}
+
+div.web-footer, div.web-footer a {
+ font-size: 90%;
+ color: #{{ get_hex_shade(doc.background_color or "ffffff", 70) }};
+}
+
+/* Bootstrap Navbar */
+.navbar-inverse .navbar-inner {
+ background-color: #{{ doc.top_bar_background or "444444"}};
+ background-repeat: repeat-x;
+ border-color: transparent;
+ background-image: none;
+}
+
+.navbar-inner {
+ box-shadow: none;
+}
+
+{% if doc.top_bar_background == doc.page_background %}.navbar-inner {
+ border-bottom: 1px solid #{{ get_hex_shade(doc.page_background or "ffffff", 15) }};
+}{% endif %}
+
+.navbar-inverse .brand,
+.navbar-inverse .brand:hover,
+.navbar-inverse .brand:focus,
+.navbar-inverse .nav > li > a {
+ color: #{{ doc.top_bar_foreground or "fffffff"}};
+ text-shadow: none;
+}
+
+.navbar-inverse .nav > li > a:hover,
+.navbar-inverse .nav > li > a:focus {
+ color: #{{ doc.top_bar_background or "0000000"}};
+}
+
+.navbar-inverse .navbar-text {
+ color: #999999;
+}
+
+.navbar-inverse .nav > li > a:focus,
+.navbar-inverse .nav > li > a:hover {
+ color: #{{ doc.top_bar_foreground or "fffffff"}};
+ background-color: transparent;
+}
+
+.navbar-inverse .nav .active > a,
+.navbar-inverse .nav .active > a:hover,
+.navbar-inverse .nav .active > a:focus {
+ color: #{{ doc.top_bar_foreground or "fffffff"}};
+ background-color: transparent;
+}
+
+.navbar-inverse .navbar-link {
+ color: #999999;
+}
+
+.navbar-inverse .navbar-link:hover,
+.navbar-inverse .navbar-link:focus {
+ color: #{{ doc.top_bar_foreground or "fffffff"}};
+}
+
+.navbar-fixed-top .navbar-inner,
+.navbar-static-top .navbar-inner {
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+ box-shadow: none;
+
+}
+.navbar .nav > .active > a,
+.navbar .nav > .active > a:hover,
+.navbar .nav > .active > a:focus {
+ color: #424242;
+ text-decoration: none;
+ background-color: transparent;
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+ box-shadow: none;
+}
+
+.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret,
+.navbar-inverse .nav li.dropdown > .dropdown-toggle:hover .caret {
+ border-top-color: #{{ doc.top_bar_foreground or "fffffff"}};
+ border-bottom-color: #{{ doc.top_bar_foreground or "fffffff"}};
+}
+
+.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,
+.navbar-inverse .nav li.dropdown.open > .dropdown-toggle:hover .caret {
+ border-top-color: #{{ doc.top_bar_background or "0000000"}};
+ border-bottom-color: #{{ doc.top_bar_background or "0000000"}};
+}
+
+.navbar-inverse .nav li.dropdown.open > .dropdown-toggle {
+ color: #{{ doc.top_bar_background or "0000000"}};
+ background-color: #{{ doc.top_bar_foreground or "fffffff"}};
+}
+
+@media (max-width: 800px) {
+ .navbar-inverse .nav-collapse .nav > li > a,
+ .navbar-inverse .nav-collapse .dropdown-menu a {
+ background-color: #{{ doc.top_bar_background or "0000000"}};
+ color: #{{ doc.top_bar_foreground or "fffffff"}};
+ }
+ .navbar-inverse .nav-collapse .nav > li > a:hover,
+ .navbar-inverse .nav-collapse .dropdown-menu a:hover {
+ background-color: #{{ doc.top_bar_foreground or "fffffff"}};
+ color: #{{ doc.top_bar_background or "0000000"}};
+ }
+
+ .navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {
+ border-top-color: #{{ doc.top_bar_foreground or "fffffff" }};
+ border-bottom-color: #{{ doc.top_bar_foreground or "fffffff" }};
+ }
+
+ .navbar-inverse .nav li.dropdown > .dropdown-toggle:hover .caret {
+ border-top-color: #{{ doc.top_bar_background or "0000000" }};
+ border-bottom-color: #{{ doc.top_bar_background or "0000000" }};
+ }
+
+ .navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,
+ .navbar-inverse .nav li.dropdown.open > .dropdown-toggle:hover .caret {
+ border-top-color: #{{ doc.top_bar_background or "0000000" }};
+ border-bottom-color: #{{ doc.top_bar_background or "0000000" }};
+ }
+
+}
+
+.breadcrumb {
+ background-color: #{{ get_hex_shade(doc.page_background or "ffffff", 10) }};
+}
+
+.breadcrumb > li {
+ text-shadow: none;
+}
+
+.breadcrumb > li > .divider {
+ color: #{{ doc.page_text }};
+}
+
+.breadcrumb > .active {
+ color: #{{ doc.page_text }};
+}
+
+
+.table-striped tbody > tr:nth-child(odd) > td,
+.table-striped tbody > tr:nth-child(odd) > th {
+ background-color: #{{ get_hex_shade(doc.page_background or "ffffff", 5) }};
+}
+
+.table-hover tbody tr:hover td,
+.table-hover tbody tr:hover th {
+ background-color: #{{ get_hex_shade(doc.page_background or "ffffff", 10) }};
+}
+
+.table-bordered {
+ border: 1px solid #{{ get_hex_shade(doc.page_background or "ffffff", 15) }};
+}
+
+.table th,
+.table td {
+ border-top: 1px solid #{{ get_hex_shade(doc.page_background or "ffffff", 15) }};
+}
+
+.table-bordered th,
+.table-bordered td {
+ border-left: 1px solid #{{ get_hex_shade(doc.page_background or "ffffff", 15) }};
+}
+
+
+
+.hero-unit {
+ background-color: #{{ get_hex_shade(doc.page_background or "ffffff", 15) }};
+}
+
+pre, code {
+ background-color: #{{ get_hex_shade(doc.page_background or "ffffff", 5) }};
+}
+
+hr {
+ border-top: 1px solid #{{ get_hex_shade(doc.page_background or "ffffff", 15) }};
+ border-bottom: 1px solid #{{ get_hex_shade(doc.page_background or "ffffff", 5) }};
+}
diff --git a/website/doctype/style_settings/style_settings.js b/website/doctype/style_settings/style_settings.js
index 54091a38f2a..54c4f085111 100644
--- a/website/doctype/style_settings/style_settings.js
+++ b/website/doctype/style_settings/style_settings.js
@@ -17,6 +17,9 @@
cur_frm.cscript.onload_post_render = function() {
wn.require('lib/public/js/lib/jscolor/jscolor.js');
- cur_frm.fields_dict.background_color.input.className = 'color';
+ $.each(["background_color", "page_background", "page_text", "page_links",
+ "top_bar_background", "top_bar_foreground", "page_headings"], function(i, v) {
+ cur_frm.fields_dict[v].input.className = 'color';
+ })
jscolor.bind();
}
\ No newline at end of file
diff --git a/website/doctype/style_settings/style_settings.py b/website/doctype/style_settings/style_settings.py
index 51799483d41..1cc3467d78c 100644
--- a/website/doctype/style_settings/style_settings.py
+++ b/website/doctype/style_settings/style_settings.py
@@ -15,6 +15,11 @@
# along with this program. If not, see .
from __future__ import unicode_literals
+import webnotes
+
+from webnotes.utils import cint, cstr
+from webnotes import _
+
class DocType:
def __init__(self, d, dl):
self.doc, self.doclist = d, dl
@@ -22,26 +27,70 @@ class DocType:
def validate(self):
"""make custom css"""
from jinja2 import Template
+ from website.utils import get_hex_shade
import os
+ self.validate_colors()
+
with open(os.path.join(
os.path.dirname(os.path.abspath(__file__)),
'custom_template.css'), 'r') as f:
temp = Template(f.read())
- if not self.doc.font_size:
- self.doc.font_size = '13px'
-
- self.doc.small_font_size = str(int(self.doc.font_size[:-2])-2) + 'px'
+ self.prepare()
- self.doc.custom_css = temp.render(doc = self.doc)
+ self.doc.custom_css = temp.render(doc = self.doc, get_hex_shade=get_hex_shade)
if self.doc.add_css:
self.doc.custom_css += '\n\n/* User CSS */\n\n' + self.doc.add_css
from webnotes.sessions import clear_cache
clear_cache('Guest')
+
+ from website.utils import clear_cache
+ clear_cache()
- del self.doc.fields['small_font_size']
+ for f in ["small_font_size", "at_import", "heading_text_style"]:
+ if f in self.doc.fields:
+ del self.doc.fields[f]
+
+ def validate_colors(self):
+ if (self.doc.page_background or self.doc.page_text) and \
+ self.doc.page_background==self.doc.page_text:
+ webnotes.msgprint(_("Page text and background is same color. Please change."),
+ raise_exception=1)
+
+ if (self.doc.top_bar_background or self.doc.top_bar_foreground) and \
+ self.doc.top_bar_background==self.doc.top_bar_foreground:
+ webnotes.msgprint(_("Top Bar text and background is same color. Please change."),
+ raise_exception=1)
+
+
+ def prepare(self):
+ if not self.doc.font_size:
+ self.doc.font_size = '13px'
+
+ self.doc.small_font_size = cstr(cint(self.doc.font_size[:-2])-2) + 'px'
+ self.doc.page_border = cint(self.doc.page_border)
+
+ fonts = []
+ if self.doc.google_web_font_for_heading:
+ fonts.append(self.doc.google_web_font_for_heading)
+ if self.doc.google_web_font_for_text:
+ fonts.append(self.doc.google_web_font_for_text)
+
+ fonts = list(set(fonts))
+
+ if self.doc.heading_text_as:
+ self.doc.heading_text_style = {
+ "UPPERCASE": "uppercase",
+ "Title Case":"capitalize",
+ "lowercase": "lowercase"
+ }[self.doc.heading_text_as]
+
+ self.doc.at_import = ""
+ for f in fonts:
+ self.doc.at_import += "\n@import url(http://fonts.googleapis.com/css?family=%s:400,700);" % f.replace(" ", "+")
+
def on_update(self):
"""rebuild pages"""
diff --git a/website/doctype/style_settings/style_settings.txt b/website/doctype/style_settings/style_settings.txt
index 5f53441ea81..df266a5992c 100644
--- a/website/doctype/style_settings/style_settings.txt
+++ b/website/doctype/style_settings/style_settings.txt
@@ -1,8 +1,8 @@
[
{
- "creation": "2013-01-10 16:34:32",
+ "creation": "2013-03-08 11:36:53",
"docstatus": 0,
- "modified": "2013-01-22 14:57:25",
+ "modified": "2013-03-14 11:57:20",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -24,23 +24,26 @@
"permlevel": 0
},
{
- "create": 1,
"doctype": "DocPerm",
"name": "__common__",
"parent": "Style Settings",
"parentfield": "permissions",
"parenttype": "DocType",
- "permlevel": 0,
"read": 1,
- "report": 1,
+ "report": 0,
"role": "Website Manager",
- "submit": 0,
- "write": 1
+ "submit": 0
},
{
"doctype": "DocType",
"name": "Style Settings"
},
+ {
+ "doctype": "DocField",
+ "fieldname": "color",
+ "fieldtype": "Section Break",
+ "label": "Color"
+ },
{
"description": "If image is selected, color will be ignored (attach first)",
"doctype": "DocField",
@@ -56,33 +59,109 @@
"fieldtype": "Data",
"label": "Background Color"
},
+ {
+ "doctype": "DocField",
+ "fieldname": "page_background",
+ "fieldtype": "Data",
+ "label": "Page Background"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "page_border",
+ "fieldtype": "Check",
+ "label": "Page Border"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "page_headings",
+ "fieldtype": "Data",
+ "label": "Page Headings"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "page_text",
+ "fieldtype": "Data",
+ "label": "Page Text"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "page_links",
+ "fieldtype": "Data",
+ "label": "Page Links"
+ },
{
"doctype": "DocField",
"fieldname": "cb0",
"fieldtype": "Column Break",
+ "label": "Top Bar",
"print_width": "50%",
"width": "50%"
},
+ {
+ "doctype": "DocField",
+ "fieldname": "top_bar_background",
+ "fieldtype": "Data",
+ "label": "Top Bar Background"
+ },
+ {
+ "description": "000 is black, fff is white",
+ "doctype": "DocField",
+ "fieldname": "top_bar_foreground",
+ "fieldtype": "Data",
+ "label": "Top Bar Text"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "fonts",
+ "fieldtype": "Section Break",
+ "label": "Fonts"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "heading_font",
+ "fieldtype": "Select",
+ "label": "Font (Heading)",
+ "options": "\nHelvetica Neue\nLucida Grande\nVerdana\nArial\nGeorgia\nTahoma\nLato\nOpen Sans"
+ },
{
"doctype": "DocField",
"fieldname": "font",
"fieldtype": "Select",
- "label": "Font",
+ "label": "Font (Text)",
"options": "\nHelvetica Neue\nLucida Grande\nVerdana\nArial\nGeorgia\nTahoma"
},
{
"doctype": "DocField",
"fieldname": "font_size",
"fieldtype": "Select",
- "label": "Font Size",
+ "label": "Font Size (Text)",
"options": "\n12px\n13px\n14px\n15px\n16px"
},
{
"doctype": "DocField",
- "fieldname": "heading_font",
+ "fieldname": "heading_text_as",
"fieldtype": "Select",
- "label": "Heading Font",
- "options": "\nHelvetica Neue\nLucida Grande\nVerdana\nArial\nGeorgia\nTahoma\nLato\nOpen Sans"
+ "label": "Heading Text As",
+ "options": "\nUPPERCASE\nTitle Case\nlowercase"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "column_break_13",
+ "fieldtype": "Column Break"
+ },
+ {
+ "description": "Add the name of Google Web Font e.g. \"Open Sans\"",
+ "doctype": "DocField",
+ "fieldname": "google_web_font_for_heading",
+ "fieldtype": "Data",
+ "label": "Google Web Font (Heading)"
+ },
+ {
+ "description": "Add the name of Google Web Font e.g. \"Open Sans\"",
+ "doctype": "DocField",
+ "fieldname": "google_web_font_for_text",
+ "fieldtype": "Data",
+ "label": "Google Web Font (Text)"
},
{
"doctype": "DocField",
@@ -115,6 +194,16 @@
"print_hide": 1
},
{
- "doctype": "DocPerm"
+ "create": 1,
+ "doctype": "DocPerm",
+ "permlevel": 0,
+ "write": 1
+ },
+ {
+ "amend": 0,
+ "cancel": 0,
+ "create": 0,
+ "doctype": "DocPerm",
+ "permlevel": 1
}
]
\ No newline at end of file
diff --git a/website/doctype/web_page/web_page.txt b/website/doctype/web_page/web_page.txt
index 861ac86e397..eed7d2b63b4 100644
--- a/website/doctype/web_page/web_page.txt
+++ b/website/doctype/web_page/web_page.txt
@@ -1,8 +1,8 @@
[
{
- "creation": "2013-01-27 16:31:21",
+ "creation": "2013-02-12 13:19:11",
"docstatus": 0,
- "modified": "2013-02-12 09:33:47",
+ "modified": "2013-03-11 17:41:11",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -24,18 +24,16 @@
"permlevel": 0
},
{
- "create": 1,
+ "amend": 0,
"doctype": "DocPerm",
"name": "__common__",
"parent": "Web Page",
"parentfield": "permissions",
"parenttype": "DocType",
- "permlevel": 0,
"read": 1,
"report": 1,
"role": "Website Manager",
- "submit": 0,
- "write": 1
+ "submit": 0
},
{
"doctype": "DocType",
@@ -85,6 +83,13 @@
"label": "Slideshow",
"options": "Website Slideshow"
},
+ {
+ "description": "Description for page header.",
+ "doctype": "DocField",
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "label": "Description"
+ },
{
"description": "Content in markdown format that appears on the main side of your page",
"doctype": "DocField",
@@ -143,6 +148,17 @@
"print_hide": 1
},
{
- "doctype": "DocPerm"
+ "cancel": 1,
+ "create": 1,
+ "doctype": "DocPerm",
+ "permlevel": 0,
+ "write": 1
+ },
+ {
+ "cancel": 0,
+ "create": 0,
+ "doctype": "DocPerm",
+ "permlevel": 1,
+ "write": 0
}
]
\ No newline at end of file
diff --git a/website/doctype/website_settings/website_settings.js b/website/doctype/website_settings/website_settings.js
index cbed609040d..67e494154f7 100644
--- a/website/doctype/website_settings/website_settings.js
+++ b/website/doctype/website_settings/website_settings.js
@@ -41,4 +41,14 @@ $.extend(cur_frm.cscript, {
this.fieldobj.refresh_options(get_parent_options('top_bar_items'));
});
}
-});
\ No newline at end of file
+});
+
+cur_frm.cscript.set_banner_from_image = function(doc) {
+ if(!doc.banner_image) {
+ msgprint(wn._("Select a Banner Image first."));
+ }
+ var src = doc.banner_image;
+ if(src.indexOf("/")==-1) src = "files/" + src;
+ cur_frm.set_value("banner_html", " ");
+}
\ No newline at end of file
diff --git a/website/doctype/website_settings/website_settings.py b/website/doctype/website_settings/website_settings.py
index 88af6348ac8..714b75a75dc 100644
--- a/website/doctype/website_settings/website_settings.py
+++ b/website/doctype/website_settings/website_settings.py
@@ -31,9 +31,6 @@ class DocType:
from website.utils import clear_cache
clear_cache()
- from webnotes.sessions import clear_cache
- clear_cache('Guest')
-
def set_home_page(self):
import webnotes
diff --git a/website/doctype/website_settings/website_settings.txt b/website/doctype/website_settings/website_settings.txt
index 6af0575a360..a39144cd6ab 100644
--- a/website/doctype/website_settings/website_settings.txt
+++ b/website/doctype/website_settings/website_settings.txt
@@ -1,8 +1,8 @@
[
{
- "creation": "2013-01-25 11:35:10",
+ "creation": "2013-03-07 11:55:11",
"docstatus": 0,
- "modified": "2013-02-21 10:05:09",
+ "modified": "2013-03-13 16:25:22",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -72,24 +72,45 @@
"label": "Home Page is Products"
},
{
+ "description": "Add a banner to the site. (small banners are usually good)",
+ "doctype": "DocField",
+ "fieldname": "banner",
+ "fieldtype": "Section Break",
+ "label": "Banner"
+ },
+ {
+ "description": "Select an image of approx width 150px with a transparent background for best results.",
+ "doctype": "DocField",
+ "fieldname": "banner_image",
+ "fieldtype": "Select",
+ "label": "Banner Image",
+ "options": "attach_files:"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "set_banner_from_image",
+ "fieldtype": "Button",
+ "label": "Set Banner from Image"
+ },
+ {
+ "description": "Banner is above the Top Menu Bar.",
+ "doctype": "DocField",
+ "fieldname": "banner_html",
+ "fieldtype": "Small Text",
+ "label": "Banner HTML"
+ },
+ {
+ "description": "Menu items in the Top Bar. For setting the color of the Top Bar, go to Style Settings ",
"doctype": "DocField",
"fieldname": "top_bar",
"fieldtype": "Section Break",
"label": "Top Bar"
},
- {
- "description": "Background shade of the top menu bar",
- "doctype": "DocField",
- "fieldname": "top_bar_background",
- "fieldtype": "Select",
- "label": "Top Bar Background",
- "options": "Black\nWhite"
- },
{
"description": "Brand is what appears on the top-right of the toolbar. If it is an image, make sure it\nhas a transparent background and use the <img /> tag. Keep size as 200px x 30px",
"doctype": "DocField",
"fieldname": "brand_html",
- "fieldtype": "Text",
+ "fieldtype": "Small Text",
"label": "Brand HTML"
},
{
diff --git a/website/helpers/blog.py b/website/helpers/blog.py
index 2bff6e57088..1f25ac0145e 100644
--- a/website/helpers/blog.py
+++ b/website/helpers/blog.py
@@ -4,41 +4,51 @@
from __future__ import unicode_literals
import webnotes
import website.utils
+from webnotes import _
+
+def clear_blog_cache():
+ for blog in webnotes.conn.sql_list("""select page_name from
+ `tabBlog Post` where ifnull(published,0)=1"""):
+ website.utils.delete_page_cache(blog)
+
+ website.utils.delete_page_cache("writers")
@webnotes.whitelist(allow_guest=True)
-def get_blog_list(args=None):
- """
- args = {
- 'start': 0,
- }
- """
+def get_blog_list(start=0, by=None, category=None):
import webnotes
-
- if not args: args = webnotes.form_dict
-
+ condition = ""
+ if by:
+ condition = " and t1.blogger='%s'" % by.replace("'", "\'")
+ if category:
+ condition += " and t1.blog_category='%s'" % category.replace("'", "\'")
query = """\
select
- name, page_name, content, owner, creation as creation,
- title, (select count(name) from `tabComment` where
- comment_doctype='Blog' and comment_docname=`tabBlog`.name) as comments
- from `tabBlog`
- where ifnull(published,0)=1
- order by creation desc, name asc
- limit %s, 5""" % args.start
+ t1.title, t1.name, t1.page_name, t1.published_on as creation,
+ ifnull(t1.blog_intro, t1.content) as content,
+ t2.full_name, t2.avatar, t1.blogger,
+ (select count(name) from `tabComment` where
+ comment_doctype='Blog Post' and comment_docname=t1.name) as comments
+ from `tabBlog Post` t1, `tabBlogger` t2
+ where ifnull(t1.published,0)=1
+ and t1.blogger = t2.name
+ %(condition)s
+ order by published_on desc, name asc
+ limit %(start)s, 20""" % {"start": start, "condition": condition}
- result = webnotes.conn.sql(query, args, as_dict=1)
+ result = webnotes.conn.sql(query, as_dict=1)
# strip html tags from content
import webnotes.utils
for res in result:
from webnotes.utils import global_date_format, get_fullname
- res['full_name'] = get_fullname(res['owner'])
res['published'] = global_date_format(res['creation'])
if not res['content']:
res['content'] = website.utils.get_html(res['page_name'])
- res['content'] = split_blog_content(res['content'])
-
+ res['content'] = res['content'][:140]
+ if res.avatar and not "/" in res.avatar:
+ res.avatar = "files/" + res.avatar
+
return result
@webnotes.whitelist(allow_guest=True)
@@ -73,10 +83,10 @@ def add_comment(args=None):
# notify commentors
commentors = [d[0] for d in webnotes.conn.sql("""select comment_by from tabComment where
- comment_doctype='Blog' and comment_docname=%s and
+ comment_doctype='Blog Post' and comment_docname=%s and
ifnull(unsubscribed, 0)=0""", args.get('comment_docname'))]
- blog = webnotes.conn.sql("""select * from tabBlog where name=%s""",
+ blog = webnotes.conn.sql("""select * from `tabBlog Post` where name=%s""",
args.get('comment_docname'), as_dict=1)[0]
from webnotes.utils.email_lib.bulk import send
@@ -89,10 +99,8 @@ def add_comment(args=None):
return comment_html
@webnotes.whitelist(allow_guest=True)
-def add_subscriber():
+def add_subscriber(name, email_id):
"""add blog subscriber to lead"""
- full_name = webnotes.form_dict.get('your_name')
- email = webnotes.form_dict.get('your_email_address')
name = webnotes.conn.sql("""select name from tabLead where email_id=%s""", email)
from webnotes.model.doc import Document
@@ -104,21 +112,38 @@ def add_subscriber():
if not lead.source: lead.source = 'Blog'
lead.unsubscribed = 0
lead.blog_subscriber = 1
- lead.lead_name = full_name
+ lead.lead_name = name
lead.email_id = email
lead.save()
-
+
def get_blog_content(blog_page_name):
import website.utils
content = website.utils.get_html(blog_page_name)
- content = split_blog_content(content)
import webnotes.utils
content = webnotes.utils.escape_html(content)
return content
+
+def get_blog_template_args():
+ args = {
+ "categories": webnotes.conn.sql_list("select name from `tabBlog Category` order by name")
+ }
+ args.update(webnotes.doc("Blog Settings", "Blog Settings").fields)
+ return args
-def split_blog_content(content):
- content = content.split("")
- content = len(content) > 1 and content[1] or content[0]
- content = content.split("")
- content = content[0]
- return content
\ No newline at end of file
+def get_writers_args():
+ bloggers = webnotes.conn.sql("""select * from `tabBlogger`
+ order by posts desc""", as_dict=1)
+ for blogger in bloggers:
+ if blogger.avatar and not "/" in blogger.avatar:
+ blogger.avatar = "files/" + blogger.avatar
+
+ args = {
+ "bloggers": bloggers,
+ "texts": {
+ "all_posts_by": _("All posts by")
+ },
+ "categories": webnotes.conn.sql_list("select name from `tabBlog Category` order by name")
+ }
+
+ args.update(webnotes.doc("Blog Settings", "Blog Settings").fields)
+ return args
\ No newline at end of file
diff --git a/website/helpers/blog_feed.py b/website/helpers/blog_feed.py
index 20c78cae2a6..41c203e0ada 100644
--- a/website/helpers/blog_feed.py
+++ b/website/helpers/blog_feed.py
@@ -44,7 +44,7 @@ rss_item = u"""
%(content)s
%(link)s
%(name)s
- %(creation)s
+ %(published_on)s
"""
def generate():
@@ -57,13 +57,12 @@ def generate():
items = ''
blog_list = webnotes.conn.sql("""\
- select page_name as name, modified, creation, title from tabBlog
+ select page_name as name, published_on, modified, title, content from `tabBlog Post`
where ifnull(published,0)=1
- order by creation desc, modified desc, name asc limit 100""", as_dict=1)
+ order by published_on desc limit 20""", as_dict=1)
for blog in blog_list:
blog.link = host + '/' + blog.name + '.html'
- blog.content = get_blog_content(blog.name)
items += rss_item % blog
diff --git a/website/page/website_home/website_home.js b/website/page/website_home/website_home.js
index c6b2253df15..e1122071dde 100644
--- a/website/page/website_home/website_home.js
+++ b/website/page/website_home/website_home.js
@@ -11,11 +11,6 @@ wn.module_page["Website"] = [
description: wn._("Content web page."),
doctype:"Web Page"
},
- {
- label: wn._("Blog"),
- description: wn._("Blog entry."),
- doctype:"Blog"
- },
{
label: wn._("Website Slideshow"),
description: wn._("Embed image slideshows in website pages."),
@@ -23,6 +18,34 @@ wn.module_page["Website"] = [
},
]
},
+ {
+ title: wn._("Blog"),
+ icon: "icon-edit",
+ items: [
+ {
+ label: wn._("Blog Post"),
+ description: wn._("Single Post (article)."),
+ doctype:"Blog Post"
+ },
+ {
+ label: wn._("Blogger"),
+ description: wn._("Profile of a blog writer."),
+ doctype:"Blogger"
+ },
+ {
+ label: wn._("Blog Category"),
+ description: wn._("Categorize blog posts."),
+ doctype:"Blog Category"
+ },
+ {
+ label: wn._("Blog Settings"),
+ description: wn._("Write titles and introductions to your blog."),
+ doctype:"Blog Settings",
+ route: "Form/Blog Settings"
+ },
+ ]
+ },
+
{
title: wn._("Website Overall Settings"),
icon: "icon-wrench",
@@ -45,6 +68,7 @@ wn.module_page["Website"] = [
{
title: wn._("Special Page Settings"),
icon: "icon-wrench",
+ right: true,
items: [
{
"route":"Form/Product Settings",
diff --git a/website/templates/css/login.css b/website/templates/css/login.css
index 710f88944b1..c2a7af2521f 100644
--- a/website/templates/css/login.css
+++ b/website/templates/css/login.css
@@ -6,6 +6,7 @@
.layout-wrapper {
background-color: #fff;
+ color: #333;
padding: 10px;
box-shadow: 1px 1px 3px 3px #ccc;
font-size: 12px;
diff --git a/website/templates/html/base.html b/website/templates/html/base.html
index fa01f8aad7c..2719f8db36d 100644
--- a/website/templates/html/base.html
+++ b/website/templates/html/base.html
@@ -19,6 +19,9 @@
{% endif %}
+ {% if description %}
+
+ {% endif %}
{% block header %}
{% endblock %}
diff --git a/website/templates/html/blog_footer.html b/website/templates/html/blog_footer.html
new file mode 100644
index 00000000000..e439d147296
--- /dev/null
+++ b/website/templates/html/blog_footer.html
@@ -0,0 +1,13 @@
+
+
+ {% if categories %}
+
Explore posts by categories
+
diff --git a/website/templates/html/blog_page.html b/website/templates/html/blog_page.html
index 24dd8d7acc4..270d427f7f1 100644
--- a/website/templates/html/blog_page.html
+++ b/website/templates/html/blog_page.html
@@ -9,45 +9,48 @@
{% endblock %}
{% block content %}
-
-
{{ title }}
+
+
{{ title }}
-
By {{ full_name }} on {{ updated }}
+
+ {{ blogger_info and blogger_info.full_name or full_name }} /
+ {{ updated }}
+
{{ content_html }}
+
-
+ {% if blogger_info %}
+
+ {% include "html/blogger.html" %}
+ {% endif %}
-
Comments
+
{{ texts.comments }}
+{% include 'html/blog_footer.html' %}
{% endblock %}
\ No newline at end of file
diff --git a/website/templates/html/blogger.html b/website/templates/html/blogger.html
new file mode 100644
index 00000000000..e18f86a4dde
--- /dev/null
+++ b/website/templates/html/blogger.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/website/templates/html/comment.html b/website/templates/html/comment.html
index 1323e094d22..27baaad54db 100644
--- a/website/templates/html/comment.html
+++ b/website/templates/html/comment.html
@@ -3,12 +3,15 @@
it is to be included in the blog/blog.html template
#}
-{% for comment in comment_list %}
-
\ No newline at end of file
diff --git a/website/templates/html/product_page.html b/website/templates/html/product_page.html
index eaf4ca8ba2b..0a19efe5065 100644
--- a/website/templates/html/product_page.html
+++ b/website/templates/html/product_page.html
@@ -11,46 +11,41 @@
{% block content %}
{% include 'html/product_search_box.html' %}
{% include 'html/product_breadcrumbs.html' %}
-
-
{{ item_name }}
-
Item Code: {{ name }}
-
- {% if slideshow %}
- {% include "html/slideshow.html" %}
- {% else %}
- {% if website_image %}
-
- {% else %}
-
- {% include 'html/product_missing_image.html' %}
-
- {% endif %}
- {% endif %}
-
-
-
Product Description
+
+ {% if slideshow %}
+ {% include "html/slideshow.html" %}
+ {% else %}
+ {% if website_image %}
+
+ {% else %}
+
+ {% include 'html/product_missing_image.html' %}
+
+ {% endif %}
+ {% endif %}
+
+
+
{{ item_name }}
+
Item Code: {{ name }}
+
Product Description
{{ web_long_description or web_short_description or
"[No description given]" }}
-
{% if obj.doclist.get({"doctype":"Item Website Specification"}) %}
-
Specifications
-
- {% for d in obj.doclist.get(
- {"doctype":"Item Website Specification"}) %}
-
- {{ d.label }}
- {{ d.description }}
-
- {% endfor %}
-
+
Specifications
+
+ {% for d in obj.doclist.get(
+ {"doctype":"Item Website Specification"}) %}
+
+ {{ d.label }}
+ {{ d.description }}
+
+ {% endfor %}
+
{% endif %}
-
-
diff --git a/website/templates/html/slideshow.html b/website/templates/html/slideshow.html
index 86417245b73..e0e9038d9fd 100644
--- a/website/templates/html/slideshow.html
+++ b/website/templates/html/slideshow.html
@@ -5,10 +5,12 @@
{% for slide in obj.slides %}
+ {% if slide.heading or slide.description %}
-
{{ slide.heading }}
-
{{ slide.description }}
+ {% if slide.heading %}
{{ slide.heading }} {% endif %}
+ {% if slide.heading %}
{{ slide.description }}
{% endif %}
+ {% endif %}
{% endfor %}
diff --git a/website/templates/js/blog.js b/website/templates/js/blog.js
index 6c006de7b29..fd5a156126f 100644
--- a/website/templates/js/blog.js
+++ b/website/templates/js/blog.js
@@ -23,6 +23,15 @@ $(document).ready(function() {
$("#next-page").click(function() {
blog.get_list();
})
+
+ if(get_url_arg("by_name")) {
+ $("#blot-subtitle").html("Posts by " + get_url_arg("by_name")).toggle(true);
+ }
+
+ if(get_url_arg("category")) {
+ $("#blot-subtitle").html("Posts filed under " + get_url_arg("category")).toggle(true);
+ }
+
});
var blog = {
@@ -33,10 +42,14 @@ var blog = {
url: "server.py",
data: {
cmd: "website.helpers.blog.get_blog_list",
- start: blog.start
+ start: blog.start,
+ by: get_url_arg("by"),
+ category: get_url_arg("category")
},
dataType: "json",
success: function(data) {
+ $(".progress").toggle(false);
+ if(data.exc) console.log(data.exc);
blog.render(data.message);
}
});
@@ -51,19 +64,30 @@ var blog = {
b.comment_text = '1 comment.'
} else {
b.comment_text = b.comments + ' comments.'
- }
+ }
- $(repl('
\
-
%(comment_text)s
\
- %(content)s
\
-
Read with comments...
\
-
', b)).appendTo($wrap);
+ b.page_name = encodeURIComponent(b.page_name);
+
+ $(repl('
\
+
\
+
\
+
\
+
\
+
\
+
\
+
\
+
%(content)s
\
+
\
+ \
+ %(full_name)s wrote this on %(published)s / %(comment_text)s
\
+
\
+
', b)).appendTo($wrap);
});
blog.start += (data.length || 0);
- if(!data.length) {
+ if(!data.length || data.length < 20) {
if(blog.start) {
$("#next-page").toggle(false)
- .parent().append("
Nothing more to show.
");
+ .parent().append("
Nothing more to show.
");
} else {
$("#next-page").toggle(false)
.parent().append("
No blogs written yet.
");
diff --git a/website/templates/js/blog_page.js b/website/templates/js/blog_page.js
index d5e99709bc3..efdd6bca8af 100644
--- a/website/templates/js/blog_page.js
+++ b/website/templates/js/blog_page.js
@@ -36,7 +36,7 @@ $(document).ready(function() {
comment_by: $("[name='comment_by']").val(),
comment: $("[name='comment']").val(),
cmd: "website.helpers.blog.add_comment",
- comment_doctype: "Blog",
+ comment_doctype: "Blog Post",
comment_docname: "{{ name }}",
page_name: "{{ page_name }}",
_type: "POST"
diff --git a/website/templates/pages/about.html b/website/templates/pages/about.html
index 30d9a5d287d..380c5439ec4 100644
--- a/website/templates/pages/about.html
+++ b/website/templates/pages/about.html
@@ -7,34 +7,27 @@
{{ obj.doc.company_introduction or "
About Us Some Introduction about your company that you would like your website visitor to know. More people than you think will read your About page. People always like to know who the are doing business with. Be authentic and avoid using jargon like 'value added services' etc. Be sure to update your company history and list of key team members in Website > About Us Settings
" }}
{% if obj.doclist.get({"doctype":"Company History"}) %}
{{ obj.doc.company_history_heading or "Company History" }}
-
-
- {% for d in obj.doclist.get({"doctype":"Company History"}) %}
-
- {{ d.year }}
- {{ d.highlight }}
-
- {% endfor %}
-
-
+ {% for d in obj.doclist.get({"doctype":"Company History"}) %}
+
+
{{ d.year }}
+
{{ d.highlight }}
+
+ {% endfor %}
{% endif %}
- {% if obj.doclist.get({"doctype":"Employee"}) %}
+ {% if obj.doclist.get({"doctype":"About Us Team Member"}) %}
{{ obj.doc.team_members_heading or "Team Members" }}
-
-
- {% for d in obj.doclist.get({"doctype":"Employee"}) %}
-
-
-
-
-
-
- {{ d.employee_name }}
- {{ d.bio }}
-
- {% endfor %}
-
-
+ {% for d in obj.doclist.get({"doctype":"About Us Team Member"}) %}
+
+
+
+
+
+
+
{{ d.full_name }}
+ {{ d.bio }}
+
+
+ {% endfor %}
{% endif %}
{{ obj.doc.footer or "" }}
diff --git a/website/templates/pages/attributions.html b/website/templates/pages/attributions.html
index 2d195ba9cd6..9e4b50ddce1 100644
--- a/website/templates/pages/attributions.html
+++ b/website/templates/pages/attributions.html
@@ -12,7 +12,7 @@
{% block content %}
-
This website is made using these Awesome Open Source Projects
+
This website is made using these awesome Open Source projects
@@ -37,6 +37,10 @@
Apache HTTPD web server
The Number One HTTP Server On The Internet.
+
+ Memcached
+ Free & open source, high-performance, distributed memory object caching system.
+
Python Programming Language
The "batteries included" language that lets you write elegant code, quickly. Python Libraries:
@@ -80,6 +84,10 @@
SlickGrid
A lightning fast JavaScript grid/spreadsheet.
+
+ FullCalendar
+ FullCalendar is a jQuery plugin that provides a full-sized, drag and drop calendar.
+
Flot Charting Library
Attractive JavaScript plotting for jQuery.
@@ -96,13 +104,37 @@
JSColor - Color Picker
HTML/Javascript Color Picker.
+
+ QUnit
+ A JavaScript Unit Testing framework.
+
Downloadify - Flash Download Widget
A tiny javascript + Flash library that enables the creation and download of text files without server interaction.
+
+
+
ERPNext License: GNU/General Public License
+
+
ERPNext - Open Source, web based ERP
+
Copyright © 2012, Web Notes Technologies Pvt Ltd, India
-
Note: A link to this page must be easily accessible.
+
This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+
This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+
For complete license see http://www.gnu.org/licenses/
+
+
Note: A link to this page must be easily accessible and all other ERPNext branding must remain as it is.
+
+
For more information please write to us at support@erpnext.com
{% endblock %}
\ No newline at end of file
diff --git a/website/templates/pages/blog.html b/website/templates/pages/blog.html
index 3c2a579c757..df258e138f4 100644
--- a/website/templates/pages/blog.html
+++ b/website/templates/pages/blog.html
@@ -12,8 +12,15 @@
{% block content %}
-
Blog
+
{{ blog_title }}
+ {% if blog_introduction %}
+
{{ blog_introduction }}
+ {% endif %}
+
+
@@ -22,4 +29,5 @@
style="display:none;">More...
+{% include 'html/blog_footer.html' %}
{% endblock %}
\ No newline at end of file
diff --git a/website/templates/pages/writers.html b/website/templates/pages/writers.html
new file mode 100644
index 00000000000..bba374946cc
--- /dev/null
+++ b/website/templates/pages/writers.html
@@ -0,0 +1,17 @@
+{% extends "html/page.html" %}
+
+{% set title="Blog Writers" %}
+
+{% block content %}
+
+
Blog Writers
+ {% if writers_introduction %}
+
{{ writers_introduction }}
+ {% endif %}
+
+ {% for blogger_info in bloggers %}
+ {% include "html/blogger.html" %}
+ {% endfor %}
+
+{% include 'html/blog_footer.html' %}
+{% endblock %}
\ No newline at end of file
diff --git a/website/utils.py b/website/utils.py
index 97c03bc0491..443bde0b661 100644
--- a/website/utils.py
+++ b/website/utils.py
@@ -25,7 +25,7 @@ page_map = {
"template": 'html/web_page.html',
"condition_field": "published"
}),
- 'Blog': webnotes._dict({
+ 'Blog Post': webnotes._dict({
"template": 'html/blog_page.html',
"condition_field": "published",
}),
@@ -40,10 +40,14 @@ page_map = {
}
page_settings_map = {
- "about": "About Us Settings",
- "contact": "Contact Us Settings"
+ "about": "website.doctype.about_us_settings.about_us_settings.get_args",
+ "contact": "Contact Us Settings",
+ "blog": "website.helpers.blog.get_blog_template_args",
+ "writers": "website.helpers.blog.get_writers_args"
}
+no_cache = "message"
+
def render(page_name):
"""render html page"""
try:
@@ -66,10 +70,12 @@ def get_html(page_name):
# load from cache, if auto cache clear is falsy
if not (hasattr(conf, 'auto_cache_clear') and conf.auto_cache_clear or 0):
- html = webnotes.cache().get_value("page:" + page_name)
- from_cache = True
+ if not page_name in no_cache:
+ html = webnotes.cache().get_value("page:" + page_name)
+ from_cache = True
if not html:
+ webnotes.connect()
html = load_into_cache(page_name)
from_cache = False
@@ -155,7 +161,11 @@ def prepare_args(page_name):
'name': page_name,
})
if page_name in page_settings_map:
- args.obj = webnotes.bean(page_settings_map[page_name]).obj
+ target = page_settings_map[page_name]
+ if "." in target:
+ args.update(webnotes.get_method(target)())
+ else:
+ args.obj = webnotes.bean(page_settings_map[page_name]).obj
else:
args = get_doc_fields(page_name)
@@ -249,18 +259,13 @@ def get_outer_env(page_name, args):
args.update(ret)
settings = webnotes.doc("Website Settings", "Website Settings")
- for k in ["brand_html", "copyright", "address", "top_bar_background", "favicon",
- "facebook_share", "google_plus_one", "twitter_share", "linked_in_share", "twitter_share_via"]:
+ for k in ["banner_html", "brand_html", "copyright", "address", "twitter_share_via"
+ "favicon", "facebook_share", "google_plus_one", "twitter_share", "linked_in_share"]:
if k in settings.fields:
args[k] = settings.fields.get(k)
for k in ["facebook_share", "google_plus_one", "twitter_share", "linked_in_share"]:
args[k] = int(args.get(k) or 0)
-
- if not args.brand_html:
- args.brand_html = "ERPNext"
- if not args.top_bar_background:
- args.top_bar_background = "Black"
args.url = quote(str(get_request_site_address(full_address=True)), str(""))
args.encoded_title = quote(str(args.title or ""), str(""))
@@ -301,4 +306,32 @@ def url_for_website(url):
if url and not url.lower().startswith("http"):
return "files/" + url
else:
- return url
\ No newline at end of file
+ return url
+
+def get_hex_shade(color, percent):
+
+ def p(c):
+ v = int(c, 16) + int(int('ff', 16) * (float(percent)/100))
+ if v < 0:
+ v=0
+ if v > 255:
+ v=255
+ h = hex(v)[2:]
+ if len(h) < 2:
+ h = "0" + h
+ return h
+
+ r, g, b = color[0:2], color[2:4], color[4:6]
+
+ avg = (float(int(r, 16) + int(g, 16) + int(b, 16)) / 3)
+ # switch dark and light shades
+ if avg > 128:
+ percent = -percent
+
+ # stronger diff for darker shades
+ if percent < 25 and avg < 64:
+ percent = percent * 2
+
+ return p(r) + p(g) + p(b)
+
+
\ No newline at end of file
Be the first one to comment
+{{ texts.first_comment }}