Merge branch 'master' of https://github.com/webnotes/erpnext
This commit is contained in:
commit
d3a30d84df
@ -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))
|
||||
|
@ -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,
|
||||
}
|
||||
]]
|
||||
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,
|
||||
}
|
||||
],
|
||||
]
|
@ -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
|
||||
}
|
||||
]
|
@ -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))
|
||||
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))
|
@ -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('<span class="balance-area">'
|
||||
+ format_currency(bal[1], bal[0]) + '</span>');
|
||||
+ format_currency(treenode.data.balance, treenode.data.currency)
|
||||
+ '</span>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -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 \
|
||||
|
@ -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();
|
||||
},
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
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))
|
@ -26,6 +26,10 @@
|
||||
<td><a href="http://httpd.apache.org">Apache HTTPD web server</a></td>
|
||||
<td>The Number One HTTP Server On The Internet.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="http://memcached.org/">Memcached</a></td>
|
||||
<td>Free & open source, high-performance, distributed memory object caching system.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="http://python.org/">Python Programming Language</a></td>
|
||||
<td>The "batteries included" language that lets you write elegant code, quickly.<br><br>Python Libraries:
|
||||
|
@ -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."
|
||||
|
@ -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)
|
||||
|
@ -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());
|
||||
|
@ -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%%'
|
||||
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%%'
|
@ -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()
|
@ -1,6 +0,0 @@
|
||||
import webnotes
|
||||
|
||||
def execute():
|
||||
from website.utils import clear_cache
|
||||
clear_cache()
|
||||
|
9
patches/march_2013/p03_rename_blog_to_blog_post.py
Normal file
9
patches/march_2013/p03_rename_blog_to_blog_post.py
Normal file
@ -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)""")
|
10
patches/march_2013/p03_update_buying_amount.py
Normal file
10
patches/march_2013/p03_update_buying_amount.py
Normal file
@ -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()
|
30
patches/march_2013/p05_payment_reconciliation.py
Normal file
30
patches/march_2013/p05_payment_reconciliation.py
Normal file
@ -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")
|
||||
|
@ -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",
|
||||
]
|
@ -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);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -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<j; i++) {
|
||||
var sl = data[i];
|
||||
|
@ -44,8 +44,9 @@ erpnext.StockGridReport = wn.views.TreeGridReport.extend({
|
||||
wh.fifo_stack.push([add_qty, sl.incoming_rate, sl.posting_date]);
|
||||
} else {
|
||||
// outgoing
|
||||
|
||||
if(is_fifo) {
|
||||
if(sl.serial_no) {
|
||||
var value_diff = -1 * this.get_serialized_value_diff(sl);
|
||||
} else if(is_fifo) {
|
||||
var value_diff = this.get_fifo_value_diff(wh, sl);
|
||||
} else {
|
||||
// average rate for weighted average
|
||||
@ -102,4 +103,34 @@ erpnext.StockGridReport = wn.views.TreeGridReport.extend({
|
||||
wh.fifo_stack = fifo_stack.reverse();
|
||||
return -fifo_value_diff;
|
||||
},
|
||||
|
||||
get_serialized_value_diff: function(sl) {
|
||||
var me = this;
|
||||
|
||||
var value_diff = 0.0;
|
||||
|
||||
$.each(sl.serial_no.trim().split("\n"), function(i, serial_no) {
|
||||
if(serial_no) {
|
||||
value_diff += flt(me.serialized_buying_rates[serial_no]);
|
||||
}
|
||||
});
|
||||
|
||||
return value_diff;
|
||||
},
|
||||
|
||||
get_serialized_buying_rates: function() {
|
||||
var serialized_buying_rates = {};
|
||||
|
||||
$.each(wn.report_dump.data["Stock Ledger Entry"], function(i, sle) {
|
||||
if(sle.qty > 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;
|
||||
},
|
||||
});
|
@ -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();
|
||||
}
|
||||
});
|
||||
}
|
@ -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)
|
||||
# ===========================================================================
|
||||
|
@ -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']),
|
||||
|
@ -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",
|
||||
}
|
||||
],
|
||||
|
@ -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();
|
||||
|
@ -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"
|
||||
}]
|
||||
|
||||
|
||||
]
|
@ -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')
|
||||
|
@ -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")
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -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": {
|
||||
|
@ -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))
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
]
|
@ -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
|
||||
|
@ -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"
|
||||
}],
|
||||
]
|
@ -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)
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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'):
|
||||
|
@ -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",
|
||||
}
|
||||
]
|
||||
]
|
@ -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()
|
||||
|
@ -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,
|
||||
|
@ -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<j; i++) {
|
||||
var sl = data[i];
|
||||
|
@ -155,6 +155,7 @@ erpnext.StockLedger = erpnext.StockGridReport.extend({
|
||||
|
||||
// initialize warehouse-item map
|
||||
this.item_warehouse = {};
|
||||
this.serialized_buying_rates = this.get_serialized_buying_rates();
|
||||
var from_datetime = dateutil.str_to_obj(me.from_date + " 00:00:00");
|
||||
var to_datetime = dateutil.str_to_obj(me.to_date + " 23:59:59");
|
||||
|
||||
|
@ -36,7 +36,6 @@ def update_entries_after(args, verbose=1):
|
||||
}
|
||||
"""
|
||||
previous_sle = get_sle_before_datetime(args)
|
||||
|
||||
qty_after_transaction = flt(previous_sle.get("qty_after_transaction"))
|
||||
valuation_rate = flt(previous_sle.get("valuation_rate"))
|
||||
stock_queue = json.loads(previous_sle.get("stock_queue") or "[]")
|
||||
@ -214,7 +213,6 @@ def get_moving_average_values(qty_after_transaction, sle, valuation_rate):
|
||||
def get_fifo_values(qty_after_transaction, sle, stock_queue):
|
||||
incoming_rate = flt(sle.incoming_rate)
|
||||
actual_qty = flt(sle.actual_qty)
|
||||
|
||||
if not stock_queue:
|
||||
stock_queue.append([0, 0])
|
||||
|
||||
|
@ -164,34 +164,37 @@ def get_warehouse_list(doctype, txt, searchfield, start, page_len, filters):
|
||||
wlist.append([w])
|
||||
return wlist
|
||||
|
||||
def get_buying_amount(item_code, warehouse, qty, voucher_no, voucher_detail_no,
|
||||
def get_buying_amount(item_code, warehouse, qty, voucher_type, voucher_no, voucher_detail_no,
|
||||
stock_ledger_entries, item_sales_bom):
|
||||
if item_sales_bom.get(item_code):
|
||||
# sales bom item
|
||||
buying_amount = 0.0
|
||||
for bom_item in item_sales_bom[item_code]:
|
||||
buying_amount += _get_buying_amount(voucher_no, "[** No Item Row **]",
|
||||
item_code, warehouse, bom_item.qty * qty, stock_ledger_entries)
|
||||
buying_amount += _get_buying_amount(voucher_type, voucher_no, "[** No Item Row **]",
|
||||
bom_item.item_code, warehouse, bom_item.qty * qty, stock_ledger_entries)
|
||||
return buying_amount
|
||||
else:
|
||||
# doesn't have sales bom
|
||||
return _get_buying_amount(voucher_no, voucher_detail_no, item_code, warehouse, qty,
|
||||
stock_ledger_entries)
|
||||
return _get_buying_amount(voucher_type, voucher_no, voucher_detail_no,
|
||||
item_code, warehouse, qty, stock_ledger_entries)
|
||||
|
||||
def _get_buying_amount(voucher_no, item_row, item_code, warehouse, qty, stock_ledger_entries):
|
||||
def _get_buying_amount(voucher_type, voucher_no, item_row, item_code, warehouse, qty,
|
||||
stock_ledger_entries):
|
||||
for i, sle in enumerate(stock_ledger_entries):
|
||||
if sle.voucher_type == "Delivery Note" and sle.voucher_no == voucher_no:
|
||||
if sle.voucher_type == voucher_type and sle.voucher_no == voucher_no and \
|
||||
len(stock_ledger_entries) > 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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/* */
|
@ -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")
|
||||
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
|
||||
}
|
@ -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": "<div class=\"alert\">Link for About Us Page is \"about.html\"</div>"
|
||||
"options": "<div class=\"alert\">Link for About Us Page is \"/about\"</div>"
|
||||
},
|
||||
{
|
||||
"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"
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
]
|
@ -1 +0,0 @@
|
||||
from __future__ import unicode_literals
|
@ -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."
|
||||
]
|
@ -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"
|
||||
}
|
@ -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"
|
||||
}
|
@ -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"
|
||||
}
|
@ -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"
|
||||
}
|
@ -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"
|
||||
}
|
@ -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"
|
||||
}
|
@ -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"
|
||||
}
|
@ -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"
|
||||
}
|
@ -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"
|
||||
}
|
@ -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"
|
||||
}
|
@ -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"
|
||||
}
|
@ -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"
|
||||
}
|
0
website/doctype/blog_category/__init__.py
Normal file
0
website/doctype/blog_category/__init__.py
Normal file
14
website/doctype/blog_category/blog_category.py
Normal file
14
website/doctype/blog_category/blog_category.py
Normal file
@ -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()
|
||||
|
51
website/doctype/blog_category/blog_category.txt
Normal file
51
website/doctype/blog_category/blog_category.txt
Normal file
@ -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"
|
||||
}
|
||||
]
|
0
website/doctype/blog_post/__init__.py
Normal file
0
website/doctype/blog_post/__init__.py
Normal file
@ -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 = '<h2><a href="%s/%s.html">%s</a></h2>\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 []
|
@ -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",
|
0
website/doctype/blog_settings/__init__.py
Normal file
0
website/doctype/blog_settings/__init__.py
Normal file
8
website/doctype/blog_settings/blog_settings.py
Normal file
8
website/doctype/blog_settings/blog_settings.py
Normal file
@ -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
|
61
website/doctype/blog_settings/blog_settings.txt
Normal file
61
website/doctype/blog_settings/blog_settings.txt
Normal file
@ -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"
|
||||
}
|
||||
]
|
0
website/doctype/blogger/__init__.py
Normal file
0
website/doctype/blogger/__init__.py
Normal file
22
website/doctype/blogger/blogger.py
Normal file
22
website/doctype/blogger/blogger.py
Normal file
@ -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()
|
||||
|
102
website/doctype/blogger/blogger.txt
Normal file
102
website/doctype/blogger/blogger.txt
Normal file
@ -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"
|
||||
}
|
||||
]
|
@ -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": "<div class=\"alert\">Link for Contact Page is \"contact.html\"</div>"
|
||||
"options": "<div class=\"alert\">Link for Contact Page is \"/contact\"</div>"
|
||||
},
|
||||
{
|
||||
"description": "Address to be displayed on the Contact Page",
|
||||
|
@ -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) }};
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
@ -15,6 +15,11 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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"""
|
||||
|
@ -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 <a href=\"http://google.com/webfonts\" target=\"_blank\">Google Web Font</a> e.g. \"Open Sans\"",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "google_web_font_for_heading",
|
||||
"fieldtype": "Data",
|
||||
"label": "Google Web Font (Heading)"
|
||||
},
|
||||
{
|
||||
"description": "Add the name of <a href=\"http://google.com/webfonts\" target=\"_blank\">Google Web Font</a> 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
|
||||
}
|
||||
]
|
@ -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
|
||||
}
|
||||
]
|
@ -41,4 +41,14 @@ $.extend(cur_frm.cscript, {
|
||||
this.fieldobj.refresh_options(get_parent_options('top_bar_items'));
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
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", "<a href='/'><img src='"+ src
|
||||
+"' style='max-width: 200px;'></a>");
|
||||
}
|
@ -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
|
||||
|
@ -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 <a href=\"#Form/Style Settings\">Style Settings</a>",
|
||||
"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"
|
||||
},
|
||||
{
|
||||
|
@ -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("<!-- begin blog content -->")
|
||||
content = len(content) > 1 and content[1] or content[0]
|
||||
content = content.split("<!-- end blog content -->")
|
||||
content = content[0]
|
||||
return content
|
||||
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
|
@ -44,7 +44,7 @@ rss_item = u"""
|
||||
<description>%(content)s</description>
|
||||
<link>%(link)s</link>
|
||||
<guid>%(name)s</guid>
|
||||
<pubDate>%(creation)s</pubDate>
|
||||
<pubDate>%(published_on)s</pubDate>
|
||||
</item>"""
|
||||
|
||||
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
|
||||
|
||||
|
@ -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",
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
.layout-wrapper {
|
||||
background-color: #fff;
|
||||
color: #333;
|
||||
padding: 10px;
|
||||
box-shadow: 1px 1px 3px 3px #ccc;
|
||||
font-size: 12px;
|
||||
|
@ -19,6 +19,9 @@
|
||||
<link rel="icon" href="app/images/favicon.ico" type="image/x-icon">
|
||||
{% endif %}
|
||||
|
||||
{% if description %}
|
||||
<meta name="description" content="{{ description }}">
|
||||
{% endif %}
|
||||
|
||||
{% block header %}
|
||||
{% endblock %}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user