Compare commits

...

119 Commits

Author SHA1 Message Date
Rushabh Mehta
245c2e885a Merge branch 'hotfix' 2017-01-27 16:18:26 +05:30
Rushabh Mehta
098bd34f00 bumped to version 7.2.17 2017-01-27 16:48:25 +06:00
Rushabh Mehta
063e86a1bf [fix] remove on_update in Item 2017-01-27 16:16:08 +05:30
Rushabh Mehta
73bf1bc4b0 Merge branch 'hotfix' 2017-01-27 16:03:29 +05:30
Rushabh Mehta
5f0027a2d0 bumped to version 7.2.16 2017-01-27 16:33:29 +06:00
Rushabh Mehta
fd82f4b0d4 [minor] fix for item_group.py 2017-01-27 16:00:47 +05:30
Rushabh Mehta
83cc7c9382 Merge branch 'hotfix' 2017-01-27 15:46:07 +05:30
Rushabh Mehta
149c033c8f bumped to version 7.2.15 2017-01-27 16:16:07 +06:00
Nabin Hait
355b4110c9 Merge pull request #7583 from rohitwaghchaure/valuation_rate_issue
[Fix] Get valuation rate from item master and update stock value difference
2017-01-25 19:21:04 +05:30
Nabin Hait
cb19f52985 Update stock_controller.py 2017-01-25 19:20:35 +05:30
Rohit Waghchaure
3899d74f15 [Fix] Get valuation rate from item master and update stock value difference 2017-01-25 18:47:53 +05:30
Nabin Hait
d288909310 Merge pull request #7561 from KanchanChauhan/salary-slip-fix-abbr
Patch to update Salary Detail where Salary Component Abbr is null
2017-01-25 17:23:43 +05:30
Kanchan Chauhan
c948a4fc92 Patch to update Salary Detail where Salary Component Abbr is null 2017-01-23 16:12:45 +05:30
Makarand Bauskar
01eefafad5 [minor] minor fixes in opportunity form (#7549) 2017-01-23 12:15:36 +05:30
Nabin Hait
b736aafb8b Merge branch 'hotfix' 2017-01-20 15:40:35 +05:30
Nabin Hait
a1d3d84415 bumped to version 7.2.14 2017-01-20 16:10:35 +06:00
Nabin Hait
c1cc7b68c4 Merge pull request #7522 from nabinhait/hotfix
Get valuation rate from Item while not found based on SLE
2017-01-20 15:39:24 +05:30
Nabin Hait
4c952f48f8 Some minor fixes 2017-01-20 15:15:31 +05:30
Nabin Hait
bd1a628c55 Merge pull request #7545 from rohitwaghchaure/minor_issue
[Fix] Account user not able to access the report Payment Period Based On Invoice Date
2017-01-20 14:36:48 +05:30
Rohit Waghchaure
93c001455f [Fix] Account user not able to access the report 2017-01-20 14:18:17 +05:30
Nabin Hait
548cf183ea Merge pull request #7543 from RobertSchouten/leave_allocation_fix
[fix] remove invalid parameter from leave allocation
2017-01-20 12:54:55 +05:30
Nabin Hait
153156e31a Merge pull request #7529 from rohitwaghchaure/budget_issue
[Fix] Budget not working properly
2017-01-20 12:54:29 +05:30
Nabin Hait
a0b967f2cd Get valuation rate from Item while not found based on SLE 2017-01-20 12:50:40 +05:30
Nabin Hait
f356e539bb Update set_null_value_to_fields.py 2017-01-20 12:35:22 +05:30
Rohit Waghchaure
84b827efcd [Fix] Budget not working properly 2017-01-20 12:33:50 +05:30
robert schouten
e14e042f2f [fix] remove invalid parameter from leave allocation 2017-01-20 15:02:00 +08:00
Nabin Hait
bfcacbf2ca Merge pull request #7535 from rohitwaghchaure/landed_cost_voucher_issue
[Fix] Minor issue in landed cost voucher
2017-01-20 12:12:17 +05:30
Nabin Hait
78966fe03b Merge pull request #7524 from KanchanChauhan/date-fixes
Date fixes in Production Order
2017-01-20 12:09:46 +05:30
Rohit Waghchaure
a3a977d02a [Fix] Minor issue in landed cost voucher 2017-01-19 18:38:53 +05:30
Kanchan Chauhan
45c14ed41c [Minor] Date fix in Production Order 2017-01-19 12:22:04 +05:30
Nabin Hait
e2f4b35b11 Merge pull request #7521 from rohitwaghchaure/discount_issue
[Fix] Sales return discount issue
2017-01-18 17:05:01 +05:30
Rohit Waghchaure
56cc542eb7 [Fix] sales return discount issue 2017-01-18 14:50:24 +05:30
Nabin Hait
461e9c1e09 Merge pull request #7519 from rohitwaghchaure/print_issue
[Fix] POS print issue
2017-01-18 13:24:16 +05:30
Rohit Waghchaure
2b97cee32c [Fix] POS print issue 2017-01-18 13:21:27 +05:30
Nabin Hait
b70767b08e Merge branch 'hotfix' 2017-01-17 15:52:25 +05:30
Nabin Hait
aff2b9479d bumped to version 7.2.13 2017-01-17 16:22:25 +06:00
Nabin Hait
a987b35b72 Merge pull request #7514 from KanchanChauhan/fix-payroll
[Minor] Payroll Fix
2017-01-17 14:59:59 +05:30
Kanchan Chauhan
653303180a [Minor] Payroll Fix 2017-01-17 13:54:55 +05:30
Nabin Hait
d9e216878f Merge pull request #7513 from rohitwaghchaure/paid_amount_copy_issue
[Fix] Calculate paid amount when is pos is enabled
2017-01-17 12:38:09 +05:30
Rohit Waghchaure
f58cad6b13 [Fix] Calculate paid amount when is pos is enabled 2017-01-17 12:11:57 +05:30
Nabin Hait
0681c77f6a Merge pull request #7506 from mntechnique/hotfix
[Fix] Project: Enabled autocomplete for project users
2017-01-17 11:27:37 +05:30
Dhaifallah Alwadani
9eb830ac4f fix string translation 2017-01-17 11:13:57 +05:30
Gaurav Naik
d9b4c52046 [Fix] Project: Enabled autocomplete for project users 2017-01-16 16:01:25 +05:30
Nabin Hait
2bbf784fd8 Merge branch 'hotfix' 2017-01-16 13:04:53 +05:30
Nabin Hait
71a730a36f bumped to version 7.2.12 2017-01-16 13:34:53 +06:00
Nabin Hait
47bdf8b659 Merge pull request #7490 from rohitwaghchaure/pos_discount_issue
[Fix] Discount not working in the POS
2017-01-16 11:44:50 +05:30
Rohit Waghchaure
685f89f2b7 [Fix] Discount not working in the POS 2017-01-14 20:47:56 +05:30
Nabin Hait
5d69900f66 Merge branch 'hotfix' 2017-01-13 17:30:45 +05:30
Nabin Hait
3d26ddd790 bumped to version 7.2.11 2017-01-13 18:00:45 +06:00
Nabin Hait
e7cb911634 Salary Slip Patch Fixed 2017-01-13 17:30:06 +05:30
Nabin Hait
ca7c5275c0 Merge branch 'hotfix' 2017-01-13 17:10:51 +05:30
Nabin Hait
fd7f3240b4 bumped to version 7.2.10 2017-01-13 17:40:51 +06:00
Nabin Hait
b166caa9fb Patch fixed 2017-01-13 17:09:57 +05:30
Nabin Hait
74c56aff90 Merge branch 'hotfix' 2017-01-13 14:33:56 +05:30
Nabin Hait
45cad45420 bumped to version 7.2.9 2017-01-13 15:03:56 +06:00
Nabin Hait
90350dfb86 Merge pull request #7476 from rohitwaghchaure/draft_status_issue_after_amend
[Fix] After amend the status become cancelled even if docstatus is zero
2017-01-13 13:14:43 +05:30
Nabin Hait
e43a94de4b Merge branch 'hotfix' into draft_status_issue_after_amend 2017-01-13 13:14:32 +05:30
Nabin Hait
9698f1b923 Merge pull request #7473 from KanchanChauhan/salary-slip-before-june
Patch to add Start and End Date in Salary Slips
2017-01-13 12:53:15 +05:30
Rohit Waghchaure
29458836e4 [Fix] After amend the status become cancelled even if docstatus is zero 2017-01-13 12:51:19 +05:30
Kanchan Chauhan
b6114e672f Patch to add Start and End Date in Salary Slips 2017-01-13 12:05:03 +05:30
Nabin Hait
4bd42146ba Merge pull request #7462 from rohitwaghchaure/minor_pos_issue
[Fix] POS issues
2017-01-13 11:55:52 +05:30
Nabin Hait
8f0c060578 Merge pull request #7447 from saurabh6790/tree_param_fix
[fix] provision to handle custom mandatory params while creating node
2017-01-13 11:50:18 +05:30
Nabin Hait
17cd36b7d5 Merge pull request #7451 from saurabh6790/chequeprint_date_fix
[minor][fix] show date in user format
2017-01-13 11:36:12 +05:30
Nabin Hait
90de12fea3 Merge pull request #7446 from KanchanChauhan/fieldtype-edit-desc
[Minor] Field type of Description field changed to Text Editor
2017-01-13 11:34:51 +05:30
Nabin Hait
02b6fe0fcb Merge pull request #7443 from nabinhait/hotfix
Fetch bin details after setting warehouse based on POS Profile
2017-01-13 11:32:57 +05:30
Rohit Waghchaure
8afe267813 [Fix] POS issues 2017-01-12 15:22:02 +05:30
Saurabh
056276c60e [minor][fix] show date in user format 2017-01-11 15:50:09 +05:30
Saurabh
2f02101d7d [fix] provision to handle custom mandatory params while creating node 2017-01-11 12:41:01 +05:30
Kanchan Chauhan
595cfb9f17 [Minor] Field type of Description field changed to Text Editor 2017-01-11 12:03:15 +05:30
Nabin Hait
0287d31c0f Fetch bin details after setting warehouse based on POS Profile 2017-01-11 10:31:45 +05:30
Nabin Hait
ffa5ffe607 Merge pull request #7442 from nabinhait/hotfix
Fix for Budget against Project
2017-01-11 10:30:44 +05:30
Nabin Hait
c0eab41ec5 Fix for Budget against Project 2017-01-11 10:16:19 +05:30
Nabin Hait
1612fa1253 Merge pull request #7426 from nabinhait/hotfix
Show values based on precision and filter out zero value rows
2017-01-10 17:26:27 +05:30
Nabin Hait
20aba32318 Merge pull request #7427 from KanchanChauhan/projects-manager-role
[Minor] Added Projects Manager role
2017-01-10 17:25:16 +05:30
Kanchan Chauhan
c4aceaad7f [Minor] Added Projects Manager role 2017-01-10 16:35:54 +05:30
Nabin Hait
5dd988207f Show values based on precision and filter out zero value rows 2017-01-10 16:10:40 +05:30
Nabin Hait
b8350353ea Merge branch 'hotfix' 2017-01-10 12:30:10 +05:30
Nabin Hait
4180a37773 bumped to version 7.2.8 2017-01-10 13:00:09 +06:00
Nabin Hait
a7f616564e Merge pull request #7417 from KanchanChauhan/quick-entry-for-item
[Minor] Valuation rate in Quick entry for Item
2017-01-10 12:23:36 +05:30
Kanchan Chauhan
43e07aed2c [Minor]Valuation rate in Quick entry for Item 2017-01-10 12:06:51 +05:30
Nabin Hait
9215581345 Merge pull request #7414 from KanchanChauhan/timesheet-payroll-frequency-toggle
[Fix] Payroll Frequency toggle fix
2017-01-10 11:58:36 +05:30
Kanchan Chauhan
2b41f9d548 [Fix] Payroll Frequency toggle fix 2017-01-09 18:43:52 +05:30
Nabin Hait
ec793b4846 Merge branch 'hotfix' of git://github.com/frappe/erpnext into hotfix 2017-01-09 17:24:10 +05:30
Nabin Hait
a2fae844b6 Merge pull request #7410 from RobertSchouten/timesheet_overlap_validation
[fix] timesheet overlap validation not including modified timesheet
2017-01-09 17:15:40 +05:30
Nabin Hait
21544ca978 Merge branch 'hotfix' 2017-01-09 16:57:11 +05:30
Nabin Hait
2bb9093b9a bumped to version 7.2.7 2017-01-09 17:27:10 +06:00
Nabin Hait
f0c41b5709 Merge pull request #7412 from nabinhait/hotfix
Allow fetching same items multiple times from source doc if all qty not processed
2017-01-09 16:00:08 +05:30
Nabin Hait
1839fcca11 Merge pull request #7406 from saurabh6790/terms_and_cond_fix
[fix] if terms exists then only call render_template
2017-01-09 15:49:56 +05:30
Nabin Hait
d1eb237909 Merge pull request #7400 from rohitwaghchaure/minor_issue
Get item default warehouse
2017-01-09 15:49:14 +05:30
Nabin Hait
a9b9edd9bc Merge pull request #7392 from frappe/bcornwellmott-patch-2
Fix number of digits on report
2017-01-09 15:48:04 +05:30
Nabin Hait
07b524ee50 Merge pull request #7398 from nabinhait/filter_dashboard
Reload in_standard_filter property
2017-01-09 15:43:30 +05:30
Nabin Hait
802b4359b5 Fetch same items multiple times from source doc if all qty not processed 2017-01-09 15:32:20 +05:30
robert schouten
138c2f6b29 [fix] timesheet overlap validation not including modified timesheet 2017-01-09 12:50:35 +08:00
Saurabh
f65e8de5a5 [fix] if terms exists then only call render_template 2017-01-07 08:18:10 +05:30
bcornwellmott
34e34ed1e8 Trigger Restart of build checks 2017-01-06 17:21:16 -08:00
Rohit Waghchaure
6734c4ad5c Get item default warehouse 2017-01-06 14:39:40 +05:30
Nabin Hait
91621639e8 Reload in_standard_filter property 2017-01-06 12:54:16 +05:30
bcornwellmott
a3e7c38734 Fix number of digits on report
Currently the cells can show many digits.
2017-01-05 09:44:18 -08:00
Nabin Hait
0dab40f4a1 Merge pull request #7377 from KanchanChauhan/naming-series
[Fix] Naming series issue
2017-01-04 15:44:00 +05:30
Nabin Hait
202bcc09d5 Merge pull request #7336 from rohitwaghchaure/pos_enhancement_and_issues
[Enhancement] POS features
2017-01-04 15:15:32 +05:30
Kanchan Chauhan
0e8361d1de [Fix] Naming series issue 2017-01-03 14:29:17 +05:30
Nabin Hait
1d88c65be4 Merge pull request #7374 from rohitwaghchaure/billed_report_enhancement
[Enhancement] Consolidated billed report, changed the report type from query to script
2017-01-02 17:40:51 +05:30
Nabin Hait
c657cceffc Merge branch 'hotfix' 2017-01-02 17:26:54 +05:30
Nabin Hait
1ecf613c3c bumped to version 7.2.6 2017-01-02 17:56:54 +06:00
Nabin Hait
ceea71bcfc Merge pull request #7365 from rohitwaghchaure/terms_and_condition
minor fix
2017-01-02 17:24:42 +05:30
Nabin Hait
b0e329b803 Merge pull request #7367 from saurabh6790/sms_log_fix
[fix] status check fix
2017-01-02 17:24:25 +05:30
Nabin Hait
506120936a Merge pull request #7373 from KanchanChauhan/leave-for-absent
[Fix] Attendance validation in Leave Application
2017-01-02 17:23:45 +05:30
Nabin Hait
7fc18f359c Currency symbol for budget amount based on company 2017-01-02 17:21:34 +05:30
Nabin Hait
92254d3930 Set serial nos in DN based on FIFO based on Stock Settings 2017-01-02 17:01:27 +05:30
Rohit Waghchaure
5a383e5cdd [Enhancement] Consolidated billed report, changed type from query to script 2017-01-02 16:20:43 +05:30
Nabin Hait
06966e8e1d minor fix 2017-01-02 15:10:01 +05:30
Kanchan Chauhan
5594050104 [Fix] Attendance validation in Leave Application 2017-01-02 11:14:44 +05:30
Rohit Waghchaure
cdbacf5398 minor fix 2016-12-30 17:06:01 +05:30
Saurabh
6bbed0297b [fix] status check fix 2016-12-30 17:05:40 +05:30
Rohit Waghchaure
bef185c404 restrict user to edit the rate in the POS 2016-12-28 15:16:49 +05:30
Rohit Waghchaure
249bc6167f fix company issue 2016-12-28 00:20:08 +05:30
Rohit Waghchaure
aa9b8603b9 added paid amount in print format 2016-12-27 17:43:23 +05:30
Rohit Waghchaure
fe7a5b305f create customer from POS 2016-12-27 17:31:32 +05:30
Rohit Waghchaure
8c9c9cfc5f When a new company is made, cash account should be automatically set for Mode of Payment 2016-12-27 17:31:32 +05:30
73 changed files with 741 additions and 302 deletions

View File

@@ -2,7 +2,7 @@
from __future__ import unicode_literals
import frappe
__version__ = '7.2.5'
__version__ = '7.2.17'
def get_default_company(user=None):
'''Get default company for user'''

View File

@@ -43,9 +43,18 @@ frappe.ui.form.on('Budget', {
},
budget_against: function(frm) {
frm.trigger("set_null_value")
frm.trigger("toggle_reqd_fields")
},
set_null_value: function(frm) {
if(frm.doc.budget_against == 'Cost Center') {
frm.set_value('project', null)
} else {
frm.set_value('cost_center', null)
}
},
toggle_reqd_fields: function(frm) {
frm.toggle_reqd("cost_center", frm.doc.budget_against=="Cost Center");
frm.toggle_reqd("project", frm.doc.budget_against=="Project");

View File

@@ -22,6 +22,7 @@ class Budget(Document):
frappe.throw(_("{0} is mandatory").format(self.budget_against))
self.validate_duplicate()
self.validate_accounts()
self.set_null_value()
def validate_duplicate(self):
budget_against_field = frappe.scrub(self.budget_against)
@@ -54,25 +55,31 @@ class Budget(Document):
else:
account_list.append(d.account)
def set_null_value(self):
if self.budget_against == 'Cost Center':
self.project = None
else:
self.cost_center = None
def validate_expense_against_budget(args):
args = frappe._dict(args)
if not args.cost_center and not args.project:
return
for budget_against in [args.project, args.cost_center]:
if budget_against \
for budget_against in ['project', 'cost_center']:
if args.get(budget_against) \
and frappe.db.get_value("Account", {"name": args.account, "root_type": "Expense"}):
if args.project:
condition = "and exists(select name from `tabProject` where name=b.project)"
if args.project and budget_against == 'project':
condition = "and b.project='%s'" % frappe.db.escape(args.project)
args.budget_against_field = "Project"
elif args.cost_center:
elif args.cost_center and budget_against == 'cost_center':
cc_lft, cc_rgt = frappe.db.get_value("Cost Center", args.cost_center, ["lft", "rgt"])
condition = """and exists(select name from `tabCost Center`
where lft<=%s and rgt>=%s and name=b.cost_center)""" % (cc_lft, cc_rgt)
args.budget_against_field = "Cost Center"
args.budget_against = budget_against
args.budget_against = args.get(budget_against)
budget_records = frappe.db.sql("""
select
@@ -88,12 +95,13 @@ def validate_expense_against_budget(args):
""".format(condition=condition,
budget_against_field=frappe.scrub(args.get("budget_against_field"))),
(args.fiscal_year, args.account), as_dict=True)
validate_budget_records(args, budget_records)
if budget_records:
validate_budget_records(args, budget_records)
def validate_budget_records(args, budget_records):
for budget in budget_records:
if budget.budget_amount:
if flt(budget.budget_amount):
yearly_action = budget.action_if_annual_budget_exceeded
monthly_action = budget.action_if_accumulated_monthly_budget_exceeded

View File

@@ -9,11 +9,13 @@
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "account",
"fieldtype": "Link",
"hidden": 0,
@@ -30,6 +32,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -40,6 +43,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "budget_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -50,11 +54,13 @@
"label": "Budget Amount",
"length": 0,
"no_copy": 0,
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -72,7 +78,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-07-11 03:27:58.705376",
"modified": "2017-01-02 17:02:53.339420",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Budget Account",

View File

@@ -35,7 +35,7 @@ def create_or_update_cheque_print_format(template_name):
</span>
<span style="top:%(date_dist_from_top_edge)s cm; left:%(date_dist_from_left_edge)scm;
position: absolute;">
{{doc.reference_date or '' }}
{{ frappe.utils.formatdate(doc.reference_date) or '' }}
</span>
<span style="top:%(acc_no_dist_from_top_edge)scm;left:%(acc_no_dist_from_left_edge)scm;
position: absolute;">

View File

@@ -326,10 +326,12 @@ class JournalEntry(AccountsController):
if d.account_currency == self.company_currency:
d.exchange_rate = 1
elif not d.exchange_rate or d.exchange_rate == 1 or \
(d.reference_type in ("Sales Invoice", "Purchase Invoice") and d.reference_name and d.posting_date):
(d.reference_type in ("Sales Invoice", "Purchase Invoice")
and d.reference_name and self.posting_date):
# Modified to include the posting date for which to retreive the exchange rate
d.exchange_rate = get_exchange_rate(self.posting_date, d.account, d.account_currency, self.company,
d.reference_type, d.reference_name, d.debit, d.credit, d.exchange_rate)
d.exchange_rate = get_exchange_rate(self.posting_date, d.account, d.account_currency,
self.company, d.reference_type, d.reference_name, d.debit, d.credit, d.exchange_rate)
if not d.exchange_rate:
frappe.throw(_("Row {0}: Exchange Rate is mandatory").format(d.idx))

View File

@@ -22,7 +22,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Applicable for User",
"length": 0,
"no_copy": 0,
@@ -52,7 +51,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Series",
"length": 0,
"no_copy": 1,
@@ -84,7 +82,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Update Stock",
"length": 0,
"no_copy": 0,
@@ -112,7 +109,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Warehouse",
"length": 0,
"no_copy": 0,
@@ -142,7 +138,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Campaign",
"length": 0,
"no_copy": 0,
@@ -159,34 +154,6 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "ignore_pricing_rule",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Ignore Pricing Rule",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
@@ -199,7 +166,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -226,7 +192,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Customer",
"length": 0,
"no_copy": 0,
@@ -256,7 +221,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Company",
"length": 0,
"no_copy": 0,
@@ -286,7 +250,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Currency",
"length": 0,
"no_copy": 0,
@@ -304,6 +267,33 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "ignore_pricing_rule",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Ignore Pricing Rule",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
@@ -316,7 +306,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Allow Delete",
"length": 0,
"no_copy": 0,
@@ -332,6 +321,33 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "allow_user_to_edit_rate",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Allow user to edit Rate",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
@@ -344,7 +360,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -371,7 +386,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Sales Invoice Payment",
"length": 0,
"no_copy": 0,
@@ -400,7 +414,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -427,7 +440,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Item Groups",
"length": 0,
"no_copy": 0,
@@ -456,7 +468,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -483,7 +494,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Customer Groups",
"length": 0,
"no_copy": 0,
@@ -512,7 +522,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -540,7 +549,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Print Format",
"length": 0,
"no_copy": 0,
@@ -569,7 +577,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Letter Head",
"length": 0,
"no_copy": 0,
@@ -599,7 +606,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Print Heading",
"length": 0,
"no_copy": 0,
@@ -629,7 +635,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Terms and Conditions",
"length": 0,
"no_copy": 0,
@@ -659,7 +664,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"oldfieldtype": "Column Break",
@@ -687,7 +691,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Territory",
"length": 0,
"no_copy": 0,
@@ -717,7 +720,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Price List",
"length": 0,
"no_copy": 0,
@@ -747,7 +749,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Apply Discount",
"length": 0,
"no_copy": 0,
@@ -777,7 +778,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Apply Discount On",
"length": 0,
"no_copy": 0,
@@ -806,7 +806,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -834,7 +833,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Write Off Account",
"length": 0,
"no_copy": 0,
@@ -863,7 +861,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Write Off Cost Center",
"length": 0,
"no_copy": 0,
@@ -892,7 +889,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Account for Change Amount",
"length": 0,
"no_copy": 0,
@@ -921,7 +917,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Taxes and Charges",
"length": 0,
"no_copy": 0,
@@ -951,7 +946,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -978,7 +972,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Income Account",
"length": 0,
"no_copy": 0,
@@ -1009,7 +1002,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Expense Account",
"length": 0,
"no_copy": 0,
@@ -1037,7 +1029,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Cost Center",
"length": 0,
"no_copy": 0,
@@ -1067,8 +1058,8 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-12-12 17:02:22.323006",
"modified_by": "Administrator",
"modified": "2016-12-28 15:14:59.411457",
"modified_by": "rohit@erpnext.com",
"module": "Accounts",
"name": "POS Profile",
"owner": "Administrator",

View File

@@ -109,12 +109,16 @@ def apply_pricing_rule(args):
item_list = args.get("items")
args.pop("items")
set_serial_nos_based_on_fifo = frappe.db.get_single_value("Stock Settings",
"automatically_set_serial_nos_based_on_fifo")
for item in item_list:
args_copy = copy.deepcopy(args)
args_copy.update(item)
out.append(get_pricing_rule_for_item(args_copy))
out.append(get_serial_no_for_item(args_copy))
if set_serial_nos_based_on_fifo:
out.append(get_serial_no_for_item(args_copy))
return out
def get_serial_no_for_item(args):

View File

@@ -39,13 +39,21 @@ def get_pos_data():
'pricing_rules': get_pricing_rule_data(doc),
'print_template': print_template,
'pos_profile': pos_profile,
'meta': {
'invoice': frappe.get_meta('Sales Invoice'),
'items': frappe.get_meta('Sales Invoice Item'),
'taxes': frappe.get_meta('Sales Taxes and Charges')
}
'meta': get_meta()
}
def get_meta():
doctype_meta = {
'customer': frappe.get_meta('Customer'),
'invoice': frappe.get_meta('Sales Invoice')
}
for row in frappe.get_all('DocField', fields = ['fieldname', 'options'],
filters = {'parent': 'Sales Invoice', 'fieldtype': 'Table'}):
doctype_meta[row.fieldname] = frappe.get_meta(row.options)
return doctype_meta
def get_company_data(company):
return frappe.get_all('Company', fields = ["*"], filters= {'name': company})[0]
@@ -62,10 +70,10 @@ def update_pos_profile_data(doc, pos_profile, company_data):
doc.currency = pos_profile.get('currency') or company_data.default_currency
doc.conversion_rate = 1.0
if doc.currency != company_data.default_currency:
doc.conversion_rate = get_exchange_rate(doc.currency, company_data.default_currency, doc.posting_date)
doc.selling_price_list = pos_profile.get('selling_price_list') or \
frappe.db.get_value('Selling Settings', None, 'selling_price_list')
doc.naming_series = pos_profile.get('naming_series') or 'SINV-'
@@ -74,6 +82,7 @@ def update_pos_profile_data(doc, pos_profile, company_data):
doc.apply_discount_on = pos_profile.get('apply_discount_on') if pos_profile.get('apply_discount') else ''
doc.customer_group = pos_profile.get('customer_group') or get_root('Customer Group')
doc.territory = pos_profile.get('territory') or get_root('Territory')
doc.terms = frappe.db.get_value('Terms and Conditions', pos_profile.get('tc_name'), 'terms') or doc.terms or ''
def get_root(table):
root = frappe.db.sql(""" select name from `tab%(table)s` having

View File

@@ -3188,6 +3188,7 @@
"ignore_xss_filter": 0,
"in_filter": 1,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Status",
"length": 0,
"no_copy": 1,
@@ -4182,7 +4183,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2016-11-09 14:18:24.760263",
"modified": "2017-01-18 13:21:13.226318",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",

View File

@@ -651,32 +651,34 @@ class SalesInvoice(SellingController):
def make_pos_gl_entries(self, gl_entries):
if cint(self.is_pos):
for payment_mode in self.payments:
# POS, make payment entries
gl_entries.append(
self.get_gl_dict({
"account": self.debit_to,
"party_type": "Customer",
"party": self.customer,
"against": payment_mode.account,
"credit": payment_mode.base_amount,
"credit_in_account_currency": payment_mode.base_amount \
if self.party_account_currency==self.company_currency \
else payment_mode.amount,
"against_voucher": self.return_against if cint(self.is_return) else self.name,
"against_voucher_type": self.doctype,
}, self.party_account_currency)
)
if payment_mode.amount:
# POS, make payment entries
gl_entries.append(
self.get_gl_dict({
"account": self.debit_to,
"party_type": "Customer",
"party": self.customer,
"against": payment_mode.account,
"credit": payment_mode.base_amount,
"credit_in_account_currency": payment_mode.base_amount \
if self.party_account_currency==self.company_currency \
else payment_mode.amount,
"against_voucher": self.return_against if cint(self.is_return) else self.name,
"against_voucher_type": self.doctype,
}, self.party_account_currency)
)
payment_mode_account_currency = get_account_currency(payment_mode.account)
gl_entries.append(
self.get_gl_dict({
"account": payment_mode.account,
"against": self.customer,
"debit": payment_mode.base_amount,
"debit_in_account_currency": payment_mode.base_amount \
if payment_mode_account_currency==self.company_currency else payment_mode.amount
}, payment_mode_account_currency)
)
payment_mode_account_currency = get_account_currency(payment_mode.account)
gl_entries.append(
self.get_gl_dict({
"account": payment_mode.account,
"against": self.customer,
"debit": payment_mode.base_amount,
"debit_in_account_currency": payment_mode.base_amount \
if payment_mode_account_currency==self.company_currency \
else payment_mode.amount
}, payment_mode_account_currency)
)
def make_gle_for_change_amount(self, gl_entries):
if cint(self.is_pos) and self.change_amount:

View File

@@ -325,6 +325,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
$.each(this.meta, function(i, data){
frappe.meta.sync(data)
locals["DocType"][data.name] = data;
})
this.print_template_data = frappe.render_template("print_template",
@@ -412,21 +413,26 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
autoFocus: true,
source: function (request, response) {
me.customer_data = me.get_customers(request.term)
me.add_customer();
response($.map(me.customer_data, function(data){
return {label: data.name, value: data.name,
customer_group: data.customer_group, territory: data.territory}
return {label: data.name, customer_name: data.name, customer_group: data.customer_group,
territory: data.territory, onclick: data.onclick}
}))
},
change: function(event, ui){
if(ui.item){
me.frm.doc.customer = ui.item.label;
me.frm.doc.customer_name = ui.item.customer_name;
me.frm.doc.customer_group = ui.item.customer_group;
me.frm.doc.territory = ui.item.territory;
}else{
me.frm.doc.customer = me.party_field.$input.val();
select: function(event, ui){
if(ui.item.onclick) {
ui.item.value = ""
ui.item.onclick(me);
}else if(ui.item) {
me.update_customer_data(ui.item)
}
me.refresh();
},
change: function(event, ui) {
if(!ui.item) {
me.frm.doc.customer = $(this).val();
}
}
}).on("focus", function(){
setTimeout(function() {
@@ -434,7 +440,43 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
me.party_field.$input.autocomplete( "search", " " );
}
}, 500);
});
}).autocomplete(this.party_field).data('ui-autocomplete')._renderItem = function(ul, d){
var html = "<span>" + __(d.label) + "</span>";
return $('<li></li>')
.data('item.autocomplete', d)
.html('<a><p>' + html + '</p></a>')
.appendTo(ul);
}
},
add_customer: function() {
var me = this;
if(this.connection_status) {
this.customer_data.push({
name: "<span class='text-primary link-option'>"
+ "<i class='fa fa-plus' style='margin-right: 5px;'></i> "
+ __("Create a new Customer")
+ "</span>",
onclick: me.new_customer
});
}
},
new_customer: function(obj) {
var me = obj;
frappe.ui.form.quick_entry('Customer', function(doc){
me.customers.push(doc)
me.party_field.$input.val(doc.name);
me.update_customer_data(doc)
})
},
update_customer_data: function(doc) {
var me = this;
this.frm.doc.customer = doc.label || doc.name;
this.frm.doc.customer_name = doc.customer_name;
this.frm.doc.customer_group = doc.customer_group;
this.frm.doc.territory = doc.territory;
},
get_customers: function(key){
@@ -593,7 +635,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
this.remove_item = []
$.each(this.frm.doc["items"] || [], function(i, d) {
if(d.serial_no){
if(d.serial_no && field == 'qty'){
me.validate_serial_no_qty(d, item_code, field, value)
}
@@ -764,6 +806,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
actual_qty: me.actual_qty_dict[d.item_code] || 0,
projected_qty: d.projected_qty,
rate: format_number(d.rate, me.frm.doc.currency),
enabled: me.pos_profile_data["allow_user_to_edit_rate"] ? true: false,
amount: format_currency(d.amount, me.frm.doc.currency)
})).appendTo($items);
});

View File

@@ -1,4 +1,5 @@
{
"align_labels_left": 0,
"creation": "2016-05-05 17:16:18.564460",
"custom_format": 1,
"disabled": 0,
@@ -6,13 +7,16 @@
"docstatus": 0,
"doctype": "Print Format",
"font": "Default",
"html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ company }}<br>\n\t{{ __(\"POS No : \") }}{{offline_pos_name}}<br>\n</p>\n<p>\n\t<b>{{ __(\"Date\") }}:</b> {{ dateutil.global_date_format(posting_date) }}<br>\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"50%\">{{ __(\"Item\") }}</b></th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ __(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ __(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{% for item in items %}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_name }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ format_number(item.qty, precision(\"difference\")) }}<br>@ {{ format_currency(item.rate, currency) }}</td>\n\t\t\t<td class=\"text-right\">{{ format_currency(item.amount, currency) }}</td>\n\t\t</tr>\n\t\t{% endfor %}\n\t</tbody>\n</table>\n\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ __(\"Net Total\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(total, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% for row in taxes %}\n\t\t{% if not row.included_in_print_rate %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ row.description }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(row.tax_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% endif %}\n\t\t{% endfor %}\n\t\t{% if discount_amount %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ __(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(discount_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% endif %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ __(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(grand_total, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t</tbody>\n</table>\n\n\n<hr>\n<p class=\"text-center\">{{ __(\"Thank you, please visit again.\") }}</p>",
"html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ company }}<br>\n\t{{ __(\"POS No : \") }}{{offline_pos_name}}<br>\n</p>\n<p>\n\t<b>{{ __(\"Date\") }}:</b> {{ dateutil.global_date_format(posting_date) }}<br>\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"50%\">{{ __(\"Item\") }}</b></th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ __(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ __(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{% for item in items %}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_name }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ format_number(item.qty, precision(\"difference\")) }}<br>@ {{ format_currency(item.rate, currency) }}</td>\n\t\t\t<td class=\"text-right\">{{ format_currency(item.amount, currency) }}</td>\n\t\t</tr>\n\t\t{% endfor %}\n\t</tbody>\n</table>\n\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ __(\"Net Total\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(total, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% for row in taxes %}\n\t\t{% if not row.included_in_print_rate %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ row.description }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(row.tax_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% endif %}\n\t\t{% endfor %}\n\t\t{% if discount_amount %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ __(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(discount_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% endif %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ __(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(grand_total, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ __(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(paid_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t</tbody>\n</table>\n\n\n<hr>\n<p>{{ terms }}</p>\n<p class=\"text-center\">{{ __(\"Thank you, please visit again.\") }}</p>",
"idx": 0,
"modified": "2016-09-05 08:28:42.308782",
"line_breaks": 0,
"modified": "2017-01-12 14:56:12.571032",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Point of Sale",
"owner": "Administrator",
"print_format_builder": 0,
"print_format_type": "Js",
"show_section_headings": 0,
"standard": "Yes"
}

View File

@@ -0,0 +1,8 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.query_reports["Delivered Items To Be Billed"] = {
"filters": [
]
}

View File

@@ -7,7 +7,7 @@
"doctype": "Report",
"idx": 1,
"is_standard": "Yes",
"modified": "2016-08-18 14:29:50.680329",
"modified": "2017-01-02 16:13:27.369266",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Delivered Items To Be Billed",
@@ -15,5 +15,5 @@
"query": "select\n `tabDelivery Note`.`name` as \"Delivery Note:Link/Delivery Note:120\",\n\t`tabDelivery Note`.`customer` as \"Customer:Link/Customer:120\",\n\t`tabDelivery Note`.`customer_name` as \"Customer Name::150\",\n\t`tabDelivery Note`.`posting_date` as \"Date:Date\",\n\t`tabDelivery Note`.`project` as \"Project\",\n\t`tabDelivery Note Item`.`item_code` as \"Item:Link/Item:120\",\n\t(`tabDelivery Note Item`.`base_amount` - `tabDelivery Note Item`.`billed_amt`*ifnull(`tabDelivery Note`.conversion_rate, 1)) as \"Pending Amount:Currency:110\",\n\t`tabDelivery Note Item`.`item_name` as \"Item Name::150\",\n\t`tabDelivery Note Item`.`description` as \"Description::200\",\n\t`tabDelivery Note`.`company` as \"Company:Link/Company:\"\nfrom `tabDelivery Note`, `tabDelivery Note Item`\nwhere \n `tabDelivery Note`.name = `tabDelivery Note Item`.parent \n and `tabDelivery Note`.docstatus = 1 \n and `tabDelivery Note`.`status` not in (\"Stopped\", \"Closed\") \n and `tabDelivery Note Item`.amount > 0\n and `tabDelivery Note Item`.billed_amt < `tabDelivery Note Item`.amount\norder by `tabDelivery Note`.`name` desc",
"ref_doctype": "Sales Invoice",
"report_name": "Delivered Items To Be Billed",
"report_type": "Query Report"
"report_type": "Script Report"
}

View File

@@ -0,0 +1,26 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from erpnext.accounts.report.non_billed_report import get_ordered_to_be_billed_data
def execute(filters=None):
columns = get_column()
args = get_args()
data = get_ordered_to_be_billed_data(args)
return columns, data
def get_column():
return [
_("Delivery Note") + ":Link/Delivery Note:120", _("Date") + ":Date:100",
_("Suplier") + ":Link/Customer:120", _("Customer Name") + "::120",
_("Project") + ":Link/Project:120", _("Item Code") + ":Link/Item:120",
_("Amount") + ":Currency:100", _("Billed Amount") + ":Currency:100", _("Pending Amount") + ":Currency:100",
_("Item Name") + "::120", _("Description") + "::120", _("Company") + ":Link/Company:120",
]
def get_args():
return {'doctype': 'Delivery Note', 'party': 'customer',
'date': 'posting_date', 'order': 'name', 'order_by': 'desc'}

View File

@@ -0,0 +1,38 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from erpnext import get_default_currency
from frappe.model.meta import get_field_precision
def get_ordered_to_be_billed_data(args):
doctype, party = args.get('doctype'), args.get('party')
child_tab = doctype + " Item"
precision = get_field_precision(frappe.get_meta(child_tab).get_field("billed_amt"),
currency=get_default_currency()) or 2
project_field = get_project_field(doctype, party)
return frappe.db.sql("""
Select
`{parent_tab}`.name, `{parent_tab}`.{date_field}, `{parent_tab}`.{party}, `{parent_tab}`.{party}_name,
{project_field}, `{child_tab}`.item_code, `{child_tab}`.base_amount,
(`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1)),
(`{child_tab}`.base_amount - (`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1))),
`{child_tab}`.item_name, `{child_tab}`.description, `{parent_tab}`.company
from
`{parent_tab}`, `{child_tab}`
where
`{parent_tab}`.name = `{child_tab}`.parent and `{parent_tab}`.docstatus = 1 and `{parent_tab}`.status != 'Closed'
and `{child_tab}`.amount > 0 and round(`{child_tab}`.billed_amt *
ifnull(`{parent_tab}`.conversion_rate, 1), {precision}) < `{child_tab}`.base_amount
order by
`{parent_tab}`.{order} {order_by}
""".format(parent_tab = 'tab' + doctype, child_tab = 'tab' + child_tab, precision= precision, party = party,
date_field = args.get('date'), project_field = project_field, order= args.get('order'), order_by = args.get('order_by')))
def get_project_field(doctype, party):
if party == "supplier": doctype = doctype + ' Item'
return "`tab%s`.project"%(doctype)

View File

@@ -0,0 +1,8 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.query_reports["Ordered Items To Be Billed"] = {
"filters": [
]
}

View File

@@ -7,7 +7,7 @@
"doctype": "Report",
"idx": 1,
"is_standard": "Yes",
"modified": "2016-08-18 14:29:50.680329",
"modified": "2017-01-02 14:53:06.277319",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Ordered Items To Be Billed",
@@ -15,5 +15,5 @@
"query": "select \n `tabSales Order`.`name` as \"Sales Order:Link/Sales Order:120\",\n `tabSales Order`.`customer` as \"Customer:Link/Customer:120\",\n `tabSales Order`.`customer_name` as \"Customer Name:150\",\n`tabSales Order`.`status` as \"Status\",\n `tabSales Order`.`transaction_date` as \"Date:Date\",\n `tabSales Order`.`project` as \"Project\",\n `tabSales Order Item`.item_code as \"Item:Link/Item:120\",\n `tabSales Order Item`.base_amount as \"Amount:Currency:110\",\n (`tabSales Order Item`.billed_amt * ifnull(`tabSales Order`.conversion_rate, 1)) as \"Billed Amount:Currency:110\",\n (`tabSales Order Item`.base_amount - (`tabSales Order Item`.billed_amt * ifnull(`tabSales Order`.conversion_rate, 1))) as \"Pending Amount:Currency:120\",\n `tabSales Order Item`.item_name as \"Item Name::150\",\n `tabSales Order Item`.description as \"Description::200\",\n `tabSales Order`.`company` as \"Company:Link/Company:\"\nfrom\n `tabSales Order`, `tabSales Order Item`\nwhere\n `tabSales Order Item`.`parent` = `tabSales Order`.`name`\n and `tabSales Order`.docstatus = 1\n and `tabSales Order`.status != \"Closed\"\n and `tabSales Order Item`.amount > 0\n and `tabSales Order Item`.billed_amt < `tabSales Order Item`.amount\norder by `tabSales Order`.transaction_date asc",
"ref_doctype": "Sales Invoice",
"report_name": "Ordered Items To Be Billed",
"report_type": "Query Report"
"report_type": "Script Report"
}

View File

@@ -0,0 +1,26 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from erpnext.accounts.report.non_billed_report import get_ordered_to_be_billed_data
def execute(filters=None):
columns = get_column()
args = get_args()
data = get_ordered_to_be_billed_data(args)
return columns, data
def get_column():
return [
_("Sales Order") + ":Link/Sales Order:120", _("Date") + ":Date:100",
_("Suplier") + ":Link/Customer:120", _("Customer Name") + "::120",
_("Project") + ":Link/Project:120", _("Item Code") + ":Link/Item:120",
_("Amount") + ":Currency:100", _("Billed Amount") + ":Currency:100", _("Pending Amount") + ":Currency:100",
_("Item Name") + "::120", _("Description") + "::120", _("Company") + ":Link/Company:120",
]
def get_args():
return {'doctype': 'Sales Order', 'party': 'customer',
'date': 'transaction_date', 'order': 'transaction_date', 'order_by': 'asc'}

View File

@@ -46,7 +46,7 @@ def validate_filters(filters):
def get_columns(filters):
return [
_("Payment Document") + ":Link/DocType: 100",
_("Payment Document") + ":: 100",
_("Payment Entry") + ":Dynamic Link/"+_("Payment Document")+":140",
_("Party Type") + "::100",
_("Party") + ":Dynamic Link/Party Type:140",

View File

@@ -0,0 +1,8 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.query_reports["Purchase Order Items To Be Billed"] = {
"filters": [
]
}

View File

@@ -7,7 +7,7 @@
"doctype": "Report",
"idx": 1,
"is_standard": "Yes",
"modified": "2016-08-18 15:46:45.789536",
"modified": "2017-01-02 12:08:36.400900",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Order Items To Be Billed",
@@ -15,5 +15,5 @@
"query": "select \n `tabPurchase Order`.`name` as \"Purchase Order:Link/Purchase Order:120\",\n `tabPurchase Order`.`transaction_date` as \"Date:Date:100\",\n\t`tabPurchase Order`.`supplier` as \"Supplier:Link/Supplier:120\",\n\t`tabPurchase Order`.`supplier_name` as \"Supplier Name::150\",\n\t`tabPurchase Order Item`.`project` as \"Project\",\n\t`tabPurchase Order Item`.item_code as \"Item Code:Link/Item:120\",\n\t`tabPurchase Order Item`.base_amount as \"Amount:Currency:100\",\n\t(`tabPurchase Order Item`.billed_amt * ifnull(`tabPurchase Order`.conversion_rate, 1)) as \"Billed Amount:Currency:100\", \n\t(`tabPurchase Order Item`.base_amount - (`tabPurchase Order Item`.billed_amt * ifnull(`tabPurchase Order`.conversion_rate, 1))) as \"Amount to Bill:Currency:100\",\n\t`tabPurchase Order Item`.item_name as \"Item Name::150\",\n\t`tabPurchase Order Item`.description as \"Description::200\",\n\t`tabPurchase Order`.company as \"Company:Link/Company:\"\nfrom\n\t`tabPurchase Order`, `tabPurchase Order Item`\nwhere\n\t`tabPurchase Order Item`.`parent` = `tabPurchase Order`.`name`\n\tand `tabPurchase Order`.docstatus = 1\n\tand `tabPurchase Order`.status != \"Closed\"\n and `tabPurchase Order Item`.amount > 0\n\tand (`tabPurchase Order Item`.billed_amt * ifnull(`tabPurchase Order`.conversion_rate, 1)) < `tabPurchase Order Item`.base_amount\norder by `tabPurchase Order`.transaction_date asc",
"ref_doctype": "Purchase Invoice",
"report_name": "Purchase Order Items To Be Billed",
"report_type": "Query Report"
"report_type": "Script Report"
}

View File

@@ -0,0 +1,26 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from erpnext.accounts.report.non_billed_report import get_ordered_to_be_billed_data
def execute(filters=None):
columns = get_column()
args = get_args()
data = get_ordered_to_be_billed_data(args)
return columns, data
def get_column():
return [
_("Purchase Order") + ":Link/Purchase Order:120", _("Date") + ":Date:100",
_("Suplier") + ":Link/Supplier:120", _("Suplier Name") + "::120",
_("Project") + ":Link/Project:120", _("Item Code") + ":Link/Item:120",
_("Amount") + ":Currency:100", _("Billed Amount") + ":Currency:100", _("Amount to Bill") + ":Currency:100",
_("Item Name") + "::120", _("Description") + "::120", _("Company") + ":Link/Company:120",
]
def get_args():
return {'doctype': 'Purchase Order', 'party': 'supplier',
'date': 'transaction_date', 'order': 'transaction_date', 'order_by': 'asc'}

View File

@@ -0,0 +1,8 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.query_reports["Received Items To Be Billed"] = {
"filters": [
]
}

View File

@@ -7,7 +7,7 @@
"doctype": "Report",
"idx": 1,
"is_standard": "Yes",
"modified": "2016-08-18 14:32:20.965816",
"modified": "2017-01-02 16:05:01.929390",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Received Items To Be Billed",
@@ -15,5 +15,5 @@
"query": "select\n `tabPurchase Receipt`.`name` as \"Purchase Receipt:Link/Purchase Receipt:120\",\n `tabPurchase Receipt`.`supplier` as \"Supplier:Link/Supplier:120\",\n\t`tabPurchase Receipt`.`supplier_name` as \"Supplier Name::150\",\n\t`tabPurchase Receipt`.`posting_date` as \"Date:Date\",\n\t`tabPurchase Receipt Item`.`project` as \"Project\",\n\t`tabPurchase Receipt Item`.`item_code` as \"Item:Link/Item:120\",\n\t(`tabPurchase Receipt Item`.`base_amount` - `tabPurchase Receipt Item`.`billed_amt`*ifnull(`tabPurchase Receipt`.conversion_rate, 1)) as \"Pending Amount:Currency:110\",\n\t`tabPurchase Receipt Item`.`item_name` as \"Item Name::150\",\n\t`tabPurchase Receipt Item`.`description` as \"Description::200\",\n\t`tabPurchase Receipt`.`company` as \"Company:Link/Company:\"\nfrom `tabPurchase Receipt`, `tabPurchase Receipt Item`\nwhere\n `tabPurchase Receipt`.name = `tabPurchase Receipt Item`.parent \n and `tabPurchase Receipt`.docstatus = 1 \n and `tabPurchase Receipt`.status != \"Closed\" \n and `tabPurchase Receipt Item`.amount > 0\n and `tabPurchase Receipt Item`.billed_amt < `tabPurchase Receipt Item`.amount\norder by `tabPurchase Receipt`.`name` desc",
"ref_doctype": "Purchase Invoice",
"report_name": "Received Items To Be Billed",
"report_type": "Query Report"
"report_type": "Script Report"
}

View File

@@ -0,0 +1,26 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from erpnext.accounts.report.non_billed_report import get_ordered_to_be_billed_data
def execute(filters=None):
columns = get_column()
args = get_args()
data = get_ordered_to_be_billed_data(args)
return columns, data
def get_column():
return [
_("Purchase Receipt") + ":Link/Purchase Receipt:120", _("Date") + ":Date:100",
_("Suplier") + ":Link/Supplier:120", _("Suplier Name") + "::120",
_("Project") + ":Link/Project:120", _("Item Code") + ":Link/Item:120",
_("Amount") + ":Currency:100", _("Billed Amount") + ":Currency:100", _("Amount to Bill") + ":Currency:100",
_("Item Name") + "::120", _("Description") + "::120", _("Company") + ":Link/Company:120",
]
def get_args():
return {'doctype': 'Purchase Receipt', 'party': 'supplier',
'date': 'posting_date', 'order': 'name', 'order_by': 'desc'}

View File

@@ -206,9 +206,12 @@ def get_count_on(account, fieldname, date):
@frappe.whitelist()
def add_ac(args=None):
from frappe.desk.treeview import make_tree_args
if not args:
args = frappe.local.form_dict
args.pop("cmd")
args = make_tree_args(**args)
ac = frappe.new_doc("Account")
@@ -233,9 +236,12 @@ def add_ac(args=None):
@frappe.whitelist()
def add_cc(args=None):
from frappe.desk.treeview import make_tree_args
if not args:
args = frappe.local.form_dict
args.pop("cmd")
args = make_tree_args(**args)
cc = frappe.new_doc("Cost Center")
cc.update(args)

View File

@@ -2212,7 +2212,7 @@
"ignore_xss_filter": 0,
"in_filter": 1,
"in_list_view": 0,
"in_standard_filter": 0,
"in_standard_filter": 1,
"label": "Status",
"length": 0,
"no_copy": 1,
@@ -2360,7 +2360,7 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"in_standard_filter": 0,
"label": "% Billed",
"length": 0,
"no_copy": 1,
@@ -3062,7 +3062,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-11-07 06:01:00.233621",
"modified": "2017-01-06 12:51:56.556331",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",

View File

@@ -3,6 +3,7 @@
from __future__ import unicode_literals
from erpnext.setup.utils import get_exchange_rate
from frappe.utils import flt, cint
import frappe
def execute(filters=None):
@@ -20,6 +21,7 @@ def get_quote_list(item, qty_list):
price_data = []
suppliers = []
company_currency = frappe.db.get_default("currency")
float_precision = cint(frappe.db.get_default("float_precision")) or 2
# Get the list of suppliers
for root in frappe.db.sql("""select parent, qty, rate from `tabSupplier Quotation Item` where item_code=%s and docstatus < 2""", item, as_dict=1):
for splr in frappe.db.sql("""SELECT supplier from `tabSupplier Quotation` where name =%s and docstatus < 2""", root.parent, as_dict=1):
@@ -46,7 +48,7 @@ def get_quote_list(item, qty_list):
# Get the quantity for this row
for item_price in price_data:
if str(item_price.qty) == col.key and item_price.supplier == root:
row[col.key] = item_price.rate * exchange_rate
row[col.key] = flt(item_price.rate * exchange_rate, float_precision)
row[col.key + "QUOTE"] = item_price.parent
break
else:

View File

@@ -223,7 +223,8 @@ class BuyingController(StockController):
})
if not rm.rate:
from erpnext.stock.stock_ledger import get_valuation_rate
rm.rate = get_valuation_rate(bom_item.item_code, self.supplier_warehouse)
rm.rate = get_valuation_rate(bom_item.item_code, self.supplier_warehouse,
self.doctype, self.name)
else:
rm.rate = bom_item.rate

View File

@@ -198,6 +198,7 @@ def make_return_doc(doctype, source_name, target_doc=None):
if tax.charge_type == "Actual":
tax.tax_amount = -1 * tax.tax_amount
doc.discount_amount = -1 * source.discount_amount
doc.run_method("calculate_taxes_and_totals")
def update_item(source_doc, target_doc, source_parent):

View File

@@ -103,6 +103,8 @@ class StatusUpdater(Document):
def set_status(self, update=False, status=None, update_modified=True):
if self.is_new():
if self.get('amended_from'):
self.status = 'Draft'
return
if self.doctype in status_map:

View File

@@ -9,6 +9,7 @@ import frappe.defaults
from erpnext.accounts.utils import get_fiscal_year
from erpnext.accounts.general_ledger import make_gl_entries, delete_gl_entries, process_gl_map
from erpnext.controllers.accounts_controller import AccountsController
from erpnext.stock.stock_ledger import get_valuation_rate
class StockController(AccountsController):
def validate(self):
@@ -51,8 +52,9 @@ class StockController(AccountsController):
# from warehouse account
self.check_expense_account(item_row)
if not sle.stock_value_difference:
self.update_stock_ledger_entries(sle)
self.validate_negative_stock(sle)
gl_list.append(self.get_gl_dict({
@@ -84,12 +86,19 @@ class StockController(AccountsController):
"\n".join(warehouse_with_no_account))
return process_gl_map(gl_list)
def update_stock_ledger_entries(self, sle):
sle.valuation_rate = get_valuation_rate(sle.item_code, sle.warehouse,
sle.voucher_type, sle.voucher_no)
sle.stock_value = flt(sle.qty_after_transaction) * flt(sle.valuation_rate)
sle.stock_value_difference = sle.stock_value
sle.doctype="Stock Ledger Entry"
frappe.get_doc(sle).db_update()
def validate_negative_stock(self, sle):
if sle.qty_after_transaction < 0 and sle.actual_qty < 0:
frappe.throw(_("For the Item {0}, valuation rate not found for warehouse {1}. To be able to do accounting entries (for booking expenses), we need valuation rate for item {2}. Please create an incoming stock transaction, on or before {3} {4}, and then try submiting {5}")
.format(sle.item_code, sle.warehouse,
sle.item_code, sle.posting_date, sle.posting_time, self.name))
frappe.throw(_("Valuation rate not found for the Item {0}, which is required to do accounting entries (for booking expenses). Please create an incoming stock transaction or mention valuation rate in Item record, and then try submiting {1} {2}")
.format(sle.item_code, sle.voucher_type, sle.voucher_no))
def get_voucher_details(self, default_expense_account, default_cost_center, sle_map):
if self.doctype == "Stock Reconciliation":

View File

@@ -455,10 +455,12 @@ class calculate_taxes_and_totals(object):
def calculate_paid_amount(self):
paid_amount = base_paid_amount = 0.0
for payment in self.doc.get('payments'):
payment.base_amount = flt(payment.amount * self.doc.conversion_rate)
paid_amount += payment.amount
base_paid_amount += payment.base_amount
if self.doc.is_pos:
for payment in self.doc.get('payments'):
payment.base_amount = flt(payment.amount * self.doc.conversion_rate)
paid_amount += payment.amount
base_paid_amount += payment.base_amount
self.doc.paid_amount = flt(paid_amount, self.doc.precision("paid_amount"))
self.doc.base_paid_amount = flt(base_paid_amount, self.doc.precision("base_paid_amount"))

View File

@@ -23,7 +23,7 @@ frappe.ui.form.on("Opportunity", {
refresh: function(frm) {
var doc = frm.doc;
frm.events.enquiry_from(frm);
if(doc.status!=="Lost") {
if(!doc.__islocal && doc.status!=="Lost") {
if(doc.with_items){
frm.add_custom_button(__('Supplier Quotation'),
function() {
@@ -109,7 +109,7 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) {
erpnext.toggle_naming_series();
var frm = cur_frm;
if(frm.perm[0].write && doc.docstatus==0) {
if(!doc.__islocal && frm.perm[0].write && doc.docstatus==0) {
if(frm.doc.status==="Open") {
frm.add_custom_button(__("Close"), function() {
frm.set_value("status", "Closed");

View File

@@ -93,7 +93,7 @@ class LeaveAllocation(Document):
if flt(leaves_taken) > flt(self.total_leaves_allocated):
if frappe.db.get_value("Leave Type", self.leave_type, "allow_negative"):
frappe.msgprint(_("Note: Total allocated leaves {0} shouldn't be less than already approved leaves {1} for the period").format(self.total_leaves_allocated, leaves_taken), LessAllocationError)
frappe.msgprint(_("Note: Total allocated leaves {0} shouldn't be less than already approved leaves {1} for the period").format(self.total_leaves_allocated, leaves_taken))
else:
frappe.throw(_("Total allocated leaves {0} cannot be less than already approved leaves {1} for the period").format(self.total_leaves_allocated, leaves_taken), LessAllocationError)

View File

@@ -217,7 +217,7 @@ class LeaveApplication(Document):
def validate_attendance(self):
attendance = frappe.db.sql("""select name from `tabAttendance` where employee = %s and (att_date between %s and %s)
and docstatus = 1""",
and status = "Present" and docstatus = 1""",
(self.employee, self.from_date, self.to_date))
if attendance:
frappe.throw(_("Attendance for employee {0} is already marked for this day").format(self.employee),

View File

@@ -7,6 +7,7 @@ frappe.ui.form.on("Process Payroll", {
frm.doc.start_date = '';
frm.doc.end_date = '';
frm.doc.payroll_frequency = '';
frm.toggle_reqd(['payroll_frequency'], !frm.doc.salary_slip_based_on_timesheet);
},
refresh: function(frm) {
@@ -25,6 +26,10 @@ frappe.ui.form.on("Process Payroll", {
frm.trigger("set_start_end_dates");
},
salary_slip_based_on_timesheet: function(frm) {
frm.toggle_reqd(['payroll_frequency'], !frm.doc.salary_slip_based_on_timesheet);
},
payment_account: function(frm) {
frm.toggle_display(['make_bank_entry'], (frm.doc.payment_account!="" && frm.doc.payment_account!="undefined"));
},

View File

@@ -68,7 +68,7 @@ class ProcessPayroll(Document):
def check_mandatory(self):
for fieldname in ['company', 'payroll_frequency', 'start_date', 'end_date']:
for fieldname in ['company', 'start_date', 'end_date']:
if not self.get(fieldname):
frappe.throw(_("Please set {0}").format(self.meta.get_label(fieldname)))
@@ -290,10 +290,8 @@ class ProcessPayroll(Document):
@frappe.whitelist()
def get_start_end_dates(payroll_frequency, start_date=None):
'''Returns dict of start and end dates for given payroll frequency based on start_date'''
if not payroll_frequency:
frappe.throw(_("Please set Payroll Frequency first"))
if payroll_frequency == "Monthly" or payroll_frequency == "Bimonthly":
if payroll_frequency == "Monthly" or payroll_frequency == "Bimonthly" or payroll_frequency == "":
fiscal_year = get_fiscal_year(start_date)[0]
month = "%02d" % getdate(start_date).month
m = get_month_details(fiscal_year, month)

View File

@@ -10,11 +10,13 @@
"doctype": "DocType",
"document_type": "Document",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "item_code",
"fieldtype": "Link",
"hidden": 0,
@@ -32,6 +34,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 1,
@@ -42,6 +45,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "item_name",
"fieldtype": "Data",
"hidden": 0,
@@ -58,6 +62,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -68,8 +73,9 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "description",
"fieldtype": "Data",
"fieldtype": "Text Editor",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -85,6 +91,7 @@
"print_hide_if_no_value": 0,
"print_width": "300px",
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -96,6 +103,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "schedule_details",
"fieldtype": "Section Break",
"hidden": 0,
@@ -110,6 +118,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -120,6 +129,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "start_date",
"fieldtype": "Date",
"hidden": 0,
@@ -136,6 +146,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 1,
@@ -146,6 +157,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "end_date",
"fieldtype": "Date",
"hidden": 0,
@@ -162,6 +174,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 1,
@@ -172,6 +185,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "periodicity",
"fieldtype": "Select",
"hidden": 0,
@@ -189,6 +203,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -199,6 +214,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "no_of_visits",
"fieldtype": "Int",
"hidden": 0,
@@ -215,6 +231,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -225,6 +242,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "sales_person",
"fieldtype": "Link",
"hidden": 0,
@@ -242,6 +260,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -252,6 +271,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "reference",
"fieldtype": "Section Break",
"hidden": 0,
@@ -266,6 +286,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -276,6 +297,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "serial_no",
"fieldtype": "Small Text",
"hidden": 0,
@@ -292,6 +314,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -302,6 +325,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "sales_order",
"fieldtype": "Link",
"hidden": 0,
@@ -320,6 +344,7 @@
"print_hide_if_no_value": 0,
"print_width": "150px",
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 1,
@@ -338,7 +363,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-07-11 03:28:02.260189",
"modified": "2017-01-11 12:02:38.449129",
"modified_by": "Administrator",
"module": "Maintenance",
"name": "Maintenance Schedule Item",

View File

@@ -304,9 +304,9 @@ class ProductionOrder(Document):
def get_operations_data(self, data):
return {
'from_time': data.planned_start_time,
'from_time': get_datetime(data.planned_start_time),
'hours': data.time_in_mins / 60.0,
'to_time': data.planned_end_time,
'to_time': get_datetime(data.planned_end_time),
'project': self.project,
'operation': data.operation,
'operation_id': data.name,

View File

@@ -360,3 +360,7 @@ erpnext.patches.v7_1.set_sales_person_status
erpnext.patches.v7_1.repost_stock_for_deleted_bins_for_merging_items
execute:frappe.delete_doc('Desktop Icon', {'module_name': 'Profit and Loss Statment'})
erpnext.patches.v7_2.update_website_for_variant
erpnext.patches.v7_2.update_doctype_status
erpnext.patches.v7_2.update_salary_slips
erpnext.patches.v7_2.set_null_value_to_fields
erpnext.patches.v7_2.update_abbr_in_salary_slips

View File

@@ -2,5 +2,5 @@ import frappe
import erpnext.setup.install
def execute():
frappe.reload_doc("website", "doctype", "web_form_field", force=True)
frappe.reload_doc("website", "doctype", "web_form_field", force=True, reset_permissions=True)
#erpnext.setup.install.add_web_forms()

View File

@@ -0,0 +1,11 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
fields = {"Cost Center": "project", "Project": "cost_center"}
for budget_against, field in fields.items():
frappe.db.sql(""" update `tabBudget` set {field} = null
where budget_against = %s """.format(field = field), budget_against)

View File

@@ -0,0 +1,13 @@
import frappe
def execute():
frappe.reload_doctype('Salary Slip')
if not frappe.db.has_column('Salary Detail', 'abbr'):
return
salary_details = frappe.db.sql("""select abbr, salary_component, name from `tabSalary Detail`
where abbr is null or abbr = ''""", as_dict=True)
for salary_detail in salary_details:
salary_component_abbr = frappe.get_value("Salary Component", salary_detail.salary_component, "salary_component_abbr")
frappe.db.sql("""update `tabSalary Detail` set abbr = %s where name = %s""",(salary_component_abbr, salary_detail.name))

View File

@@ -0,0 +1,11 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
doctypes = ["Opportunity", "Quotation", "Sales Order", "Sales Invoice", "Purchase Invoice", "Purchase Order", "Delivery Note", "Purchase Receipt"]
for doctype in doctypes:
frappe.db.sql(""" update `tab{doctype}` set status = 'Draft'
where status = 'Cancelled' and docstatus = 0 """.format(doctype = doctype))

View File

@@ -0,0 +1,20 @@
import frappe
from erpnext.hr.doctype.process_payroll.process_payroll import get_month_details
def execute():
ss_columns = frappe.db.get_table_columns("Salary Slip")
if "fiscal_year" not in ss_columns or "month" not in ss_columns:
return
salary_slips = frappe.db.sql("""select fiscal_year, month, name from `tabSalary Slip`
where (month is not null and month != '')
and (fiscal_year is not null and fiscal_year != '') and
(start_date is null or start_date = '') and
(end_date is null or end_date = '') and docstatus != 2""", as_dict=1)
for salary_slip in salary_slips:
get_start_end_date = get_month_details(salary_slip.fiscal_year, salary_slip.month)
start_date = get_start_end_date['month_start_date']
end_date = get_start_end_date['month_end_date']
frappe.db.sql("""update `tabSalary Slip` set start_date = %s, end_date = %s where name = %s""",
(start_date, end_date, salary_slip.name))

View File

@@ -10,6 +10,7 @@
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 0,
"engine": "InnoDB",
"fields": [
{
"allow_on_submit": 0,
@@ -24,7 +25,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Project Name",
"length": 0,
"no_copy": 0,
@@ -53,7 +53,6 @@
"ignore_xss_filter": 0,
"in_filter": 1,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "Status",
"length": 0,
"no_copy": 1,
@@ -83,7 +82,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "Project Type",
"length": 0,
"no_copy": 0,
@@ -113,7 +111,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "Is Active",
"length": 0,
"no_copy": 0,
@@ -144,7 +141,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "% Complete Method",
"length": 0,
"no_copy": 0,
@@ -173,7 +169,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -200,7 +195,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "Priority",
"length": 0,
"no_copy": 0,
@@ -230,7 +224,6 @@
"ignore_xss_filter": 0,
"in_filter": 1,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Expected Start Date",
"length": 0,
"no_copy": 0,
@@ -259,7 +252,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Expected End Date",
"length": 0,
"no_copy": 0,
@@ -288,7 +280,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "% Completed",
"length": 0,
"no_copy": 1,
@@ -315,7 +306,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Customer Details",
"length": 0,
"no_copy": 0,
@@ -344,7 +334,6 @@
"ignore_xss_filter": 0,
"in_filter": 1,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Customer",
"length": 0,
"no_copy": 0,
@@ -374,7 +363,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -401,7 +389,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Sales Order",
"length": 0,
"no_copy": 0,
@@ -430,7 +417,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Users",
"length": 0,
"no_copy": 0,
@@ -459,7 +445,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Users",
"length": 0,
"no_copy": 0,
@@ -488,7 +473,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Tasks",
"length": 0,
"no_copy": 0,
@@ -517,7 +501,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Tasks",
"length": 0,
"no_copy": 0,
@@ -546,7 +529,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Notes",
"length": 0,
"no_copy": 0,
@@ -575,7 +557,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Notes",
"length": 0,
"no_copy": 0,
@@ -604,7 +585,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Start and End Dates",
"length": 0,
"no_copy": 0,
@@ -632,7 +612,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Actual Start Date",
"length": 0,
"no_copy": 0,
@@ -660,7 +639,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Actual Time (in Hours)",
"length": 0,
"no_copy": 0,
@@ -688,7 +666,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -715,7 +692,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Actual End Date",
"length": 0,
"no_copy": 0,
@@ -744,7 +720,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Costing and Billing",
"length": 0,
"no_copy": 0,
@@ -773,7 +748,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Estimated Cost",
"length": 0,
"no_copy": 0,
@@ -804,7 +778,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Total Costing Amount (via Time Logs)",
"length": 0,
"no_copy": 0,
@@ -833,7 +806,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Total Expense Claim (via Expense Claims)",
"length": 0,
"no_copy": 0,
@@ -861,7 +833,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Company",
"length": 0,
"no_copy": 0,
@@ -889,7 +860,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Default Cost Center",
"length": 0,
"no_copy": 0,
@@ -917,7 +887,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -945,7 +914,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Total Billing Amount (via Time Logs)",
"length": 0,
"no_copy": 0,
@@ -973,7 +941,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Total Purchase Cost (via Purchase Invoice)",
"length": 0,
"no_copy": 0,
@@ -1001,7 +968,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Margin",
"length": 0,
"no_copy": 0,
@@ -1030,7 +996,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Gross Margin",
"length": 0,
"no_copy": 0,
@@ -1060,7 +1025,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -1087,7 +1051,6 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Gross Margin %",
"length": 0,
"no_copy": 0,
@@ -1117,7 +1080,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 4,
"modified": "2016-11-07 05:55:56.179455",
"modified": "2017-01-10 16:33:54.691885",
"modified_by": "Administrator",
"module": "Projects",
"name": "Project",
@@ -1164,6 +1127,27 @@
"share": 0,
"submit": 0,
"write": 0
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Projects Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
],
"quick_entry": 1,

View File

@@ -8,6 +8,8 @@ from frappe.utils import flt, getdate, get_url
from frappe import _
from frappe.model.document import Document
from erpnext.controllers.queries import get_filters_cond
from frappe.desk.reportview import get_match_cond
class Project(Document):
def get_feed(self):
@@ -215,12 +217,29 @@ def get_list_context(context=None):
}
def get_users_for_project(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""select name, concat_ws(' ', first_name, middle_name, last_name)
conditions = []
return frappe.db.sql("""select name, concat_ws(' ', first_name, middle_name, last_name)
from `tabUser`
where enabled=1
and name not in ("Guest", "Administrator")
and name not in ("Guest", "Administrator")
and ({key} like %(txt)s
or full_name like %(txt)s)
{fcond} {mcond}
order by
name asc""")
if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
if(locate(%(_txt)s, full_name), locate(%(_txt)s, full_name), 99999),
idx desc,
name, full_name
limit %(start)s, %(page_len)s""".format(**{
'key': searchfield,
'fcond': get_filters_cond(doctype, filters, conditions),
'mcond': get_match_cond(doctype)
}), {
'txt': "%%%s%%" % txt,
'_txt': txt.replace("%", ""),
'start': start,
'page_len': page_len
})
@frappe.whitelist()
def get_cost_center_name(project):

View File

@@ -55,7 +55,8 @@ class Task(Document):
def update_depends_on(self):
depends_on_tasks = ""
for d in self.depends_on:
depends_on_tasks += d.task + ","
if d.task:
depends_on_tasks += d.task + ","
self.depends_on_tasks = depends_on_tasks
def on_update(self):

View File

@@ -199,13 +199,22 @@ class Timesheet(Document):
(%(to_time)s > tsd.from_time and %(to_time)s < tsd.to_time) or
(%(from_time)s <= tsd.from_time and %(to_time)s >= tsd.to_time))
and tsd.name!=%(name)s
and ts.name!=%(parent)s
and ts.docstatus < 2""".format(cond),
{
"val": value,
"from_time": args.from_time,
"to_time": args.to_time,
"name": args.name or "No Name"
"name": args.name or "No Name",
"parent": args.parent or "No Name"
}, as_dict=True)
# check internal overlap
for time_log in self.time_logs:
if (fieldname != 'workstation' or args.get(fieldname) == time_log.get(fieldname)) and \
args.idx != time_log.idx and ((args.from_time > time_log.from_time and args.from_time < time_log.to_time) or
(args.to_time > time_log.from_time and args.to_time < time_log.to_time) or
(args.from_time <= time_log.from_time and args.to_time >= time_log.to_time)):
return self
return existing[0] if existing else None
@@ -359,7 +368,8 @@ def get_events(start, end, filters=None):
conditions = get_conditions(filters)
return frappe.db.sql("""select `tabTimesheet Detail`.name as name,
`tabTimesheet Detail`.docstatus as status, `tabTimesheet Detail`.parent as parent,
from_time as start_date, hours, activity_type, project, to_time as end_date
from_time as start_date, hours, activity_type, project, to_time as end_date,
CONCAT(`tabTimesheet Detail`.parent, ' (', ROUND(hours,2),' hrs)') as title
from `tabTimesheet Detail`, `tabTimesheet`
where `tabTimesheet Detail`.parent = `tabTimesheet`.name
and `tabTimesheet`.docstatus < 2

View File

@@ -588,11 +588,13 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
calculate_paid_amount: function(){
var me = this;
var paid_amount = base_paid_amount = 0.0;
$.each(this.frm.doc['payments'] || [], function(index, data){
data.base_amount = flt(data.amount * me.frm.doc.conversion_rate, precision("base_amount"));
paid_amount += data.amount;
base_paid_amount += data.base_amount;
})
if(this.frm.doc.is_pos) {
$.each(this.frm.doc['payments'] || [], function(index, data){
data.base_amount = flt(data.amount * me.frm.doc.conversion_rate, precision("base_amount"));
paid_amount += data.amount;
base_paid_amount += data.base_amount;
})
}
this.frm.doc.paid_amount = flt(paid_amount, precision("paid_amount"));
this.frm.doc.base_paid_amount = flt(base_paid_amount, precision("base_paid_amount"));

View File

@@ -2,7 +2,7 @@
<div class="col-xs-5"><h6>{%= item_code || "" %}{%= item_name || "" %}</h6></div>
<div class="col-xs-4">
<div class="row pos-qty-row">
<div class="col-xs-2 text-center pos-qty-btn" data-action="decrease-qty"><i class="fa fa-minus-sign text-muted"></i></div>
<div class="col-xs-2 text-center pos-qty-btn" data-action="decrease-qty"><i class="fa fa-minus text-muted" style="font-size:12px"></i></div>
<div class="col-xs-8">
<div>
<input type="text" value="{%= qty %}" class="form-control input-sm pos-item-qty text-right">
@@ -13,11 +13,17 @@
</div>
{% } %}
</div>
<div class="col-xs-2 text-center pos-qty-btn" data-action="increase-qty"><i class="fa fa-plus-sign text-muted"></i></div>
<div class="col-xs-2 text-center pos-qty-btn" data-action="increase-qty"><i class="fa fa-plus text-muted" style="font-size:12px"></i></div>
</div>
</div>
<div class="col-xs-3 text-right">
<div class="text-muted" style="margin-top: 5px;"><input type="text" value="{%= rate %}" class="form-control input-sm pos-item-rate text-right"></div>
<div class="text-muted" style="margin-top: 5px;">
{% if(enabled) { %}
<input type="text" value="{%= rate %}" class="form-control input-sm pos-item-rate text-right">
{% } else { %}
<h6>{%= format_currency(rate) %}</h6>
{% } %}
</div>
<p><h6>{%= amount %}</h6></p>
</div>
</div>

View File

@@ -153,22 +153,37 @@ erpnext.utils.map_current_doc = function(opts) {
frappe.get_meta(items_doctype).fields.forEach(function(d) {
if(d.options===opts.source_doctype) link_fieldname = d.fieldname; });
// search in existing items if the source_name is already set
// search in existing items if the source_name is already set and full qty fetched
var already_set = false;
var item_qty_map = {};
$.each(cur_frm.doc.items, function(i, d) {
if(d[link_fieldname]==opts.source_name) {
already_set = true;
return false;
if (item_qty_map[d.item_code])
item_qty_map[d.item_code] += flt(d.qty);
else
item_qty_map[d.item_code] = flt(d.qty);
}
});
if(already_set) {
frappe.msgprint(__("You have already selected items from {0} {1}",
[opts.source_doctype, opts.source_name]));
return;
}
frappe.model.with_doc(opts.source_doctype, opts.source_name, function(r) {
var source_doc = frappe.model.get_doc(opts.source_doctype, opts.source_name);
$.each(source_doc.items || [], function(i, row) {
if(row.qty > flt(item_qty_map[row.item_code])) {
already_set = false;
return false;
}
})
})
if(already_set) {
frappe.msgprint(__("You have already selected items from {0} {1}",
[opts.source_doctype, opts.source_name]));
return;
}
}
}

View File

@@ -5,7 +5,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import get_datetime
from frappe.utils import getdate
from frappe.model.document import Document
class AcademicTerm(Document):
@@ -18,16 +18,18 @@ class AcademicTerm(Document):
self.title = self.academic_year + " ({})".format(self.term_name) if self.term_name else ""
#Check that start of academic year is earlier than end of academic year
if self.term_start_date and self.term_end_date and self.term_start_date > self.term_end_date:
if self.term_start_date and self.term_end_date \
and getdate(self.term_start_date) > getdate(self.term_end_date):
frappe.throw(_("The Term End Date cannot be earlier than the Term Start Date. Please correct the dates and try again."))
"""Check that the start of the term is not before the start of the academic year and end of term is not after
the end of the academic year"""
# Check that the start of the term is not before the start of the academic year
# and end of term is not after the end of the academic year"""
year = frappe.get_doc("Academic Year",self.academic_year)
if self.term_start_date and get_datetime(year.year_start_date) and (self.term_start_date < get_datetime(year.year_start_date)):
if self.term_start_date and getdate(year.year_start_date) and (getdate(self.term_start_date) < getdate(year.year_start_date)):
frappe.throw(_("The Term Start Date cannot be earlier than the Year Start Date of the Academic Year to which the term is linked (Academic Year {}). Please correct the dates and try again.").format(self.academic_year))
if self.term_end_date and get_datetime(year.year_end_date) and (self.term_end_date > get_datetime(year.year_end_date)):
if self.term_end_date and getdate(year.year_end_date) and (getdate(self.term_end_date) > getdate(year.year_end_date)):
frappe.throw(_("The Term End Date cannot be later than the Year End Date of the Academic Year to which the term is linked (Academic Year {}). Please correct the dates and try again.").format(self.academic_year))

View File

@@ -2580,7 +2580,7 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"in_standard_filter": 1,
"label": "Delivery Status",
"length": 0,
"no_copy": 1,
@@ -2610,7 +2610,7 @@
"ignore_xss_filter": 0,
"in_filter": 1,
"in_list_view": 1,
"in_standard_filter": 1,
"in_standard_filter": 0,
"label": "% Delivered",
"length": 0,
"no_copy": 1,
@@ -2668,7 +2668,7 @@
"ignore_xss_filter": 0,
"in_filter": 1,
"in_list_view": 1,
"in_standard_filter": 1,
"in_standard_filter": 0,
"label": "% Amount Billed",
"length": 0,
"no_copy": 1,
@@ -2698,7 +2698,7 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"in_standard_filter": 1,
"label": "Billing Status",
"length": 0,
"no_copy": 1,
@@ -3369,7 +3369,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-11-16 04:06:28.675876",
"modified": "2017-01-06 12:51:17.847227",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Order",
@@ -3383,7 +3383,7 @@
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 1,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,

View File

@@ -78,6 +78,8 @@ class Company(Document):
if not frappe.local.flags.ignore_chart_of_accounts:
self.set_default_accounts()
if self.default_cash_account:
self.mode_of_payment()
if self.default_currency:
frappe.db.set_value("Currency", self.default_currency, "enabled", 1)
@@ -162,6 +164,16 @@ class Company(Document):
if account:
self.db_set(fieldname, account)
def mode_of_payment(self):
cash = frappe.db.get_value('Mode of Payment', {'type': 'Cash'}, 'name')
if cash and not frappe.db.get_value('Mode of Payment Account', {'company': self.name}):
mode_of_payment = frappe.get_doc('Mode of Payment', cash)
mode_of_payment.append('accounts', {
'company': self.name,
'default_account': self.default_cash_account
})
mode_of_payment.save(ignore_permissions=True)
def create_default_cost_center(self):
cc_list = [
{

View File

@@ -40,9 +40,10 @@ class TestCompany(unittest.TestCase):
acc = frappe.get_doc("Account", account)
for prop, val in acc_property.items():
self.assertEqual(acc.get(prop), val)
self.delete_mode_of_payment("COA from Existing Company")
frappe.delete_doc("Company", "COA from Existing Company")
def test_coa_based_on_country_template(self):
countries = ["India", "Brazil", "United Arab Emirates", "Canada", "Germany", "France",
"Guatemala", "Indonesia", "Mexico", "Nicaragua", "Netherlands", "Singapore"]
@@ -78,4 +79,9 @@ class TestCompany(unittest.TestCase):
self.assertTrue(frappe.get_all("Account", filters))
finally:
frappe.delete_doc("Company", template)
self.delete_mode_of_payment(template)
frappe.delete_doc("Company", template)
def delete_mode_of_payment(self, company):
frappe.db.sql(""" delete from `tabMode of Payment Account`
where company =%s """, (company))

View File

@@ -28,7 +28,6 @@ class ItemGroup(NestedSet, WebsiteGenerator):
def on_update(self):
NestedSet.on_update(self)
WebsiteGenerator.on_update(self)
invalidate_cache_for(self)
self.validate_name_with_item()
self.validate_one_root()

View File

@@ -134,7 +134,7 @@ class NamingSeries(Document):
"""get series current"""
if self.prefix:
self.current_value = frappe.db.get_value("Series",
self.prefix.split('.')[0], "current")
self.prefix.split('.')[0], "current", order_by = "name")
def insert_series(self, series):
"""insert series if missing"""

View File

@@ -77,7 +77,7 @@ def send_via_gateway(arg):
for d in arg.get('receiver_list'):
args[ss.receiver_parameter] = d
status = send_request(ss.sms_gateway_url, args)
if status > 200 and status < 300:
if status >= 200 and status < 300:
success_list.append(d)
if len(success_list) > 0:

View File

@@ -9,7 +9,8 @@ from frappe.utils.jinja import validate_template
class TermsandConditions(Document):
def validate(self):
validate_template(self.terms)
if self.terms:
validate_template(self.terms)
@frappe.whitelist()
def get_terms_and_conditions(template_name, doc):
@@ -17,4 +18,6 @@ def get_terms_and_conditions(template_name, doc):
doc = json.loads(doc)
terms_and_conditions = frappe.get_doc("Terms and Conditions", template_name)
return frappe.render_template(terms_and_conditions.terms, doc)
if terms_and_conditions.terms:
return frappe.render_template(terms_and_conditions.terms, doc)

View File

@@ -2705,7 +2705,7 @@
"ignore_xss_filter": 0,
"in_filter": 1,
"in_list_view": 0,
"in_standard_filter": 0,
"in_standard_filter": 1,
"label": "Status",
"length": 0,
"no_copy": 1,
@@ -3120,7 +3120,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2016-12-16 03:56:08.745185",
"modified": "2017-01-06 12:52:48.960308",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Note",

View File

@@ -370,7 +370,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:(doc.__islocal && doc.is_stock_item && !doc.has_serial_no && !doc.has_batch_no && doc.opening_stock)",
"depends_on": "eval:(doc.is_stock_item && !doc.has_serial_no && !doc.has_batch_no)",
"fieldname": "valuation_rate",
"fieldtype": "Currency",
"hidden": 0,
@@ -2713,7 +2713,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 1,
"modified": "2016-12-27 12:17:44.227302",
"modified": "2017-01-18 17:43:20.262925",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item",

View File

@@ -93,7 +93,6 @@ class Item(WebsiteGenerator):
where parentfield='website_item_groups' and parenttype='Item' and parent=%s""", self.name)
def on_update(self):
super(Item, self).on_update()
invalidate_cache_for_item(self)
self.validate_name_with_item_group()
self.update_item_price()

View File

@@ -15,6 +15,7 @@
"item_group": "_Test Item Group",
"item_name": "_Test Item",
"apply_warehouse_wise_reorder_level": 1,
"valuation_rate": 100,
"reorder_levels": [
{
"material_request_type": "Purchase",
@@ -61,6 +62,7 @@
"item_code": "_Test Item Home Desktop 100",
"item_group": "_Test Item Group Desktops",
"item_name": "_Test Item Home Desktop 100",
"valuation_rate": 100,
"taxes": [
{
"doctype": "Item Tax",

View File

@@ -12,22 +12,23 @@ class LandedCostVoucher(Document):
def get_items_from_purchase_receipts(self):
self.set("items", [])
for pr in self.get("purchase_receipts"):
pr_items = frappe.db.sql("""select pr_item.item_code, pr_item.description,
pr_item.qty, pr_item.base_rate, pr_item.base_amount, pr_item.name
from `tab{doctype} Item` pr_item where parent = %s
and exists(select name from tabItem where name = pr_item.item_code and is_stock_item = 1)
""".format(doctype=pr.receipt_document_type), pr.receipt_document, as_dict=True)
if pr.receipt_document_type and pr.receipt_document:
pr_items = frappe.db.sql("""select pr_item.item_code, pr_item.description,
pr_item.qty, pr_item.base_rate, pr_item.base_amount, pr_item.name
from `tab{doctype} Item` pr_item where parent = %s
and exists(select name from tabItem where name = pr_item.item_code and is_stock_item = 1)
""".format(doctype=pr.receipt_document_type), pr.receipt_document, as_dict=True)
for d in pr_items:
item = self.append("items")
item.item_code = d.item_code
item.description = d.description
item.qty = d.qty
item.rate = d.base_rate
item.amount = d.base_amount
item.receipt_document_type = pr.receipt_document_type
item.receipt_document = pr.receipt_document
item.purchase_receipt_item = d.name
for d in pr_items:
item = self.append("items")
item.item_code = d.item_code
item.description = d.description
item.qty = d.qty
item.rate = d.base_rate
item.amount = d.base_amount
item.receipt_document_type = pr.receipt_document_type
item.receipt_document = pr.receipt_document
item.purchase_receipt_item = d.name
if self.get("taxes"):
self.set_applicable_charges_for_item()

View File

@@ -219,9 +219,9 @@ class StockEntry(StockController):
# validate qty during submit
if d.docstatus==1 and d.s_warehouse and not allow_negative_stock and d.actual_qty < d.transfer_qty:
frappe.throw(_("Row {0}: Qty not available for {4} in warehouse {1} at posting time of the entry ({2} {3})".format(d.idx,
frappe.throw(_("Row {0}: Qty not available for {4} in warehouse {1} at posting time of the entry ({2} {3})").format(d.idx,
frappe.bold(d.s_warehouse), formatdate(self.posting_date),
format_time(self.posting_time), frappe.bold(d.item_code)))
format_time(self.posting_time), frappe.bold(d.item_code))
+ '<br><br>' + _("Available qty is {0}, you need {1}").format(frappe.bold(d.actual_qty),
frappe.bold(d.transfer_qty)),
NegativeStockError, title=_('Insufficient Stock'))
@@ -867,4 +867,4 @@ def get_warehouse_details(args):
"basic_rate" : get_incoming_rate(args)
}
return ret
return ret

View File

@@ -269,26 +269,13 @@ def get_children():
@frappe.whitelist()
def add_node():
doctype = frappe.form_dict.get('doctype')
company = frappe.form_dict.get('company')
parent_field = 'parent_' + doctype.lower().replace(' ', '_')
name_field = doctype.lower().replace(' ', '_') + '_name'
from frappe.desk.treeview import make_tree_args
args = make_tree_args(**frappe.form_dict)
doc = frappe.new_doc(doctype)
if cint(args.is_root):
args.parent_warehouse = None
parent = frappe.form_dict['parent']
if cint(frappe.form_dict['is_root']):
parent = None
doc.update({
name_field: frappe.form_dict['warehouse_name'],
parent_field: parent,
"is_group": frappe.form_dict['is_group'],
"company": company
})
doc.save()
frappe.get_doc(args).insert()
@frappe.whitelist()
def convert_to_group_or_ledger():

View File

@@ -42,9 +42,6 @@ def get_item_details(args):
get_party_item_code(args, item_doc, out)
if out.get("warehouse"):
out.update(get_bin_details(args.item_code, out.warehouse))
if frappe.db.exists("Product Bundle", args.item_code):
valuation_rate = 0.0
bundled_items = frappe.get_doc("Product Bundle", args.item_code)
@@ -65,6 +62,9 @@ def get_item_details(args):
if args.customer and cint(args.is_pos):
out.update(get_pos_profile_item_details(args.company, args))
if out.get("warehouse"):
out.update(get_bin_details(args.item_code, out.warehouse))
# update args with out, if key or value not exists
for key, value in out.iteritems():
@@ -143,7 +143,7 @@ def get_basic_details(args, item):
user_default_warehouse = user_default_warehouse_list[0] \
if len(user_default_warehouse_list)==1 else ""
warehouse = user_default_warehouse or args.warehouse or item.default_warehouse
warehouse = user_default_warehouse or item.default_warehouse or args.warehouse
out = frappe._dict({
"item_code": item.name,

View File

@@ -102,7 +102,7 @@ def get_item_warehouse_map(filters):
"in_qty": 0.0, "in_val": 0.0,
"out_qty": 0.0, "out_val": 0.0,
"bal_qty": 0.0, "bal_val": 0.0,
"val_rate": 0.0, "uom": None
"val_rate": 0.0
})
qty_dict = iwb_map[(d.company, d.item_code, d.warehouse)]
@@ -129,6 +129,24 @@ def get_item_warehouse_map(filters):
qty_dict.val_rate = d.valuation_rate
qty_dict.bal_qty += qty_diff
qty_dict.bal_val += value_diff
iwb_map = filter_items_with_no_transactions(iwb_map)
return iwb_map
def filter_items_with_no_transactions(iwb_map):
for (company, item, warehouse) in sorted(iwb_map):
qty_dict = iwb_map[(company, item, warehouse)]
no_transactions = True
for key, val in qty_dict.items():
val = flt(val, 3)
qty_dict[key] = val
if key != "val_rate" and val:
no_transactions = False
if no_transactions:
iwb_map.pop((company, item, warehouse))
return iwb_map

View File

@@ -258,6 +258,10 @@ class update_entries_after(object):
if not self.valuation_rate and actual_qty > 0:
self.valuation_rate = sle.incoming_rate
if not self.valuation_rate:
self.valuation_rate = get_valuation_rate(sle.item_code, sle.warehouse,
sle.voucher_type, sle.voucher_no, self.allow_zero_rate)
def get_fifo_values(self, sle):
incoming_rate = flt(sle.incoming_rate)
@@ -281,10 +285,9 @@ class update_entries_after(object):
qty_to_pop = abs(actual_qty)
while qty_to_pop:
if not self.stock_queue:
if self.qty_after_transaction > 0:
_rate = get_valuation_rate(sle.item_code, sle.warehouse, self.allow_zero_rate)
else:
_rate = 0
# Get valuation rate from last sle if exists or from valuation rate field in item master
_rate = get_valuation_rate(sle.item_code, sle.warehouse,
sle.voucher_type, sle.voucher_no, self.allow_zero_rate)
self.stock_queue.append([0, _rate])
index = None
@@ -404,7 +407,8 @@ def get_stock_ledger_entries(previous_sle, operator=None, order="desc", limit=No
"order": order
}, previous_sle, as_dict=1, debug=debug)
def get_valuation_rate(item_code, warehouse, allow_zero_rate=False):
def get_valuation_rate(item_code, warehouse, voucher_type, voucher_no, allow_zero_rate=False):
# Get valuation rate from last sle for the same item and warehouse
last_valuation_rate = frappe.db.sql("""select valuation_rate
from `tabStock Ledger Entry`
where item_code = %s and warehouse = %s
@@ -412,6 +416,7 @@ def get_valuation_rate(item_code, warehouse, allow_zero_rate=False):
order by posting_date desc, posting_time desc, name desc limit 1""", (item_code, warehouse))
if not last_valuation_rate:
# Get valuation rate from last sle for the item against any warehouse
last_valuation_rate = frappe.db.sql("""select valuation_rate
from `tabStock Ledger Entry`
where item_code = %s and valuation_rate > 0
@@ -420,9 +425,14 @@ def get_valuation_rate(item_code, warehouse, allow_zero_rate=False):
valuation_rate = flt(last_valuation_rate[0][0]) if last_valuation_rate else 0
if not valuation_rate:
valuation_rate = frappe.db.get_value("Item Price", {"item_code": item_code, "buying": 1}, "price_list_rate")
# If negative stock allowed, and item delivered without any incoming entry,
# syste does not found any SLE, then take valuation rate from Item
valuation_rate = frappe.db.get_value("Item", item_code, "valuation_rate")
if not allow_zero_rate and not valuation_rate and cint(frappe.db.get_value("Accounts Settings", None, "auto_accounting_for_stock")):
frappe.throw(_("Purchase rate for item: {0} not found, which is required to book accounting entry (expense). Please mention item price against a buying price list.").format(item_code))
if not allow_zero_rate and not valuation_rate \
and cint(frappe.db.get_value("Accounts Settings", None, "auto_accounting_for_stock")):
frappe.throw(_("Valuation rate not found for the Item {0}, which is required to do accounting entries (for booking expenses). Please create an incoming stock transaction or mention valuation rate in Item record, and then try submiting {1} {2}")
.format(item_code, voucher_type, voucher_no))
return valuation_rate