Compare commits

...

140 Commits

Author SHA1 Message Date
Frappe Bot
402ffa8b29 Merge branch 'hotfix' 2018-12-10 12:14:33 +00:00
Frappe Bot
65a9991d84 bumped to version 10.1.75 2018-12-10 12:14:33 +00:00
Nabin Hait
3248e0bb3e Merge pull request #16163 from netchampfaris/hotfix-setupwizard-abbr
fix(setup-wizard): Validate abbr length before switching to next slide
2018-12-07 15:20:23 +05:30
Nabin Hait
1b529d997c Merge pull request #16146 from rohitwaghchaure/remove_tax_amt_from_the_billed_amt_in_project
[Fix] In project, tax amount is added in the total billed amount(sales) field
2018-12-07 15:17:35 +05:30
Nabin Hait
01ccb8b099 Merge pull request #16144 from deepeshgarg007/list_view
[Fix]List view currency bug fix
2018-12-07 15:09:09 +05:30
Deepesh Garg
6967b44ac8 Merge branch 'hotfix' into list_view 2018-12-07 08:30:20 +05:30
Frappe Bot
efb2712d14 Merge branch 'hotfix' 2018-12-06 09:14:35 +00:00
Frappe Bot
be0a349a52 bumped to version 10.1.74 2018-12-06 09:14:35 +00:00
Nabin Hait
32c95c3292 Merge pull request #16113 from nabinhait/travis-fix
fix(test): Fixed tests for discount with margin and period closing voucher
2018-12-06 11:58:56 +05:30
Faris Ansari
40c15348da fix(setup-wizard): Validate abbr length before switching to next slide 2018-12-06 07:37:32 +05:30
rohitwaghchaure
f85856d9f8 Merge pull request #16155 from rohitwaghchaure/changed_parent_for_item_attribute_value
[Fix] Permissions issue
2018-12-04 18:45:07 +05:30
Rohit Waghchaure
675567419b [Fix] Permissions issue 2018-12-04 18:43:52 +05:30
Rohit Waghchaure
636d186d08 [Fix] In project, tax amount is added in the total billed amount(sales) field 2018-12-03 16:04:08 +05:30
deepeshgarg007
114cc810a0 List view currency bug fix 2018-12-03 15:13:06 +05:30
Nabin Hait
6b93f2fe0a Merge pull request #16139 from Zlash65/fix-assess
[Minor] Assessment Result fix
2018-12-03 14:33:01 +05:30
Nabin Hait
0b4ea25f83 Merge pull request #16138 from rohitwaghchaure/user_permissions_issue_item
[Fix] Permissions issue while making item variants
2018-12-03 14:32:40 +05:30
Nabin Hait
dd7b020b01 fix(test): Fixed tests for period closing voucher 2018-12-03 14:24:41 +05:30
Nabin Hait
dce68422a7 Merge pull request #16133 from rohitwaghchaure/fixed_stock_value_diifference_calculation_for_stock_reco
[Fix] Stock value difference calculation for stock reconciliation
2018-12-03 14:20:40 +05:30
Zlash65
db43c3af68 display message if details to fetch grade isnt filled up 2018-12-03 12:15:10 +05:30
Rohit Waghchaure
a8003c1af7 [Fix] Permissions issue while making item variants 2018-12-03 11:49:52 +05:30
rohitwaghchaure
ce72d26e95 Merge pull request #16125 from frappe/revert-16112-accounts_receivable_summary_print_issue
Revert "[Fix] Accounts receivable summary print is not working"
2018-11-30 16:21:53 +05:30
Rohit Waghchaure
16b8ecbe05 [Fix] Stock value difference calculation for stock reconciliation 2018-11-30 16:20:52 +05:30
Nabin Hait
eda0a6eb33 fix(test): Fixed tests for period closing voucher 2018-11-30 15:15:17 +05:30
rohitwaghchaure
ca332bdcdb Revert "[Fix] Accounts receivable summary print is not working" 2018-11-29 18:15:29 +05:30
Ameya Shenoy
e3136c38e1 bumped to version 10.1.73 2018-11-28 07:57:27 +00:00
Nabin Hait
ce870316c5 Merge pull request #16112 from rohitwaghchaure/accounts_receivable_summary_print_issue
[Fix] Accounts receivable summary print is not working
2018-11-27 17:57:17 +05:30
Nabin Hait
f642f86982 Merge branch 'hotfix' into accounts_receivable_summary_print_issue 2018-11-27 17:56:49 +05:30
Nabin Hait
96598936ad fix(test): Fixed tests for discount with margin and period closing voucher 2018-11-27 17:48:13 +05:30
Rohit Waghchaure
10bcd5113c [Fix] Accounts receivable summary print is not working 2018-11-27 16:25:35 +05:30
Nabin Hait
b98d08a2cb Merge pull request #16049 from rohitwaghchaure/incorrect_stock_value_difference_calculation
[Fix] Incorrect stock value difference because of negative stock
2018-11-27 13:21:43 +05:30
Nabin Hait
ccb03fb255 Merge pull request #16073 from deepeshgarg007/receivable-summary
Accounts receivable summary print fix
2018-11-27 13:11:37 +05:30
Nabin Hait
3c31e4ad4b Merge pull request #16088 from rohitwaghchaure/fixed_pos_profile_packing_items
If is pos is enabled and no pos profile then use the item's default warehouse for packing materials
2018-11-27 13:10:14 +05:30
Nabin Hait
0ccc05bdf7 Merge pull request #15997 from rohitwaghchaure/address_not_set_from_api
[Fix] Address not set from the API
2018-11-26 20:17:03 +05:30
Nabin Hait
7f02659425 Merge branch 'hotfix' into address_not_set_from_api 2018-11-26 20:16:54 +05:30
Nabin Hait
2598c475ed Merge pull request #15999 from codingCoffee/css
css: build files in v10
2018-11-26 20:02:18 +05:30
Rohit Waghchaure
3893ba302c If is pos and no pos profile use the item's default warehouse for packing materials 2018-11-26 14:13:24 +05:30
deepeshgarg007
5dbb9f5312 Accounts receivable summary print fix 2018-11-23 19:54:08 +05:30
Rohit Waghchaure
6424f47f3b [Fix] Incorrect stock value difference because of negative stock 2018-11-21 23:18:41 +05:30
Ameya Shenoy
27a0c37963 css: build files in v10 2018-11-15 19:21:30 +00:00
Rohit Waghchaure
f4dc71661d [Fix] Address not set from the API 2018-11-15 17:04:02 +05:30
Frappe Bot
0b697c5298 Merge branch 'hotfix' 2018-11-15 09:04:14 +00:00
Frappe Bot
2426d00dd6 bumped to version 10.1.72 2018-11-15 09:04:14 +00:00
rohitwaghchaure
5395b164cd Merge pull request #15983 from rohitwaghchaure/fixed_claimed_amount_issue
Claimed amount is not reset on cancel of employee advance
2018-11-14 13:21:11 +05:30
Rohit Waghchaure
047a7123eb Claimed amount is not reset on cancel 2018-11-14 13:20:00 +05:30
Frappe Bot
cb1726d6ec Merge branch 'hotfix' 2018-11-13 10:55:31 +00:00
Frappe Bot
6b78e520d2 bumped to version 10.1.71 2018-11-13 10:55:31 +00:00
khushalti
fad08e1bcb [fix] - GL entry not creating on PR if rejected qty mentoned (#15815) 2018-11-13 12:09:32 +05:30
Ameya Shenoy
3d58576797 Merge pull request #15963 from codingCoffee/frankfurter
fix: changed currency exchange API to frankfurter
2018-11-12 17:55:48 +05:30
Ameya Shenoy
438490fd29 fix: changed currency exchange API to frankfurter
- Switched to Frankfurter's public API (frankfurter.app) from
self hosted API (frankfurter.erpnext.org)
2018-11-12 15:15:06 +05:30
Frappe Bot
f001a9eb4f Merge branch 'hotfix' 2018-11-09 10:09:04 +00:00
Frappe Bot
f8a5cfe8d8 bumped to version 10.1.70 2018-11-09 10:09:04 +00:00
rohitwaghchaure
a88eaa6e20 [Fix] User able to change discount if pricing rule has discount value as zero (#15921) 2018-11-08 13:05:08 +05:30
Nabin Hait
6ff2f395f5 fix(gle): Post gl entry for booking COGS from Sales Invoice even if grand_total is zero (#15825) 2018-11-08 12:30:44 +05:30
Frappe Bot
ccff3e2aec Merge branch 'hotfix' 2018-11-07 11:26:10 +00:00
Frappe Bot
7f37d26f05 bumped to version 10.1.69 2018-11-07 11:26:10 +00:00
Shreya Shah
c704630d5f fix: Return default if company not found (#15915) 2018-11-06 17:24:45 +05:30
Ameya Shenoy
1a41929c6b Merge branch 'hotfix' 2018-11-06 11:02:04 +00:00
Ameya Shenoy
a97a520aa8 bumped to version 10.1.68 2018-11-06 11:02:04 +00:00
Nabin Hait
3e6663d47e fix(serial no): Set supplier info based on pur invoice if serial no is created from Purchase Invoice (#15820) 2018-11-05 14:01:59 +05:30
Ameya Shenoy
eeb66dfc8e Merge branch 'hotfix' 2018-11-05 06:40:25 +00:00
Ameya Shenoy
59f16bc942 bumped to version 10.1.67 2018-11-05 06:40:25 +00:00
rohitwaghchaure
e77f38e7e2 Merge pull request #15894 from rohitwaghchaure/fix_update_claimed_amount
Column ‘claimed_amount’ cannot be null
2018-11-02 18:14:08 +05:30
Rohit Waghchaure
598d34445f [Fix] Column ‘claimed_amount’ cannot be null 2018-11-02 16:02:33 +05:30
Navdeep Ghai
768513f2f9 fixed divided by zero error (#15885) 2018-11-02 12:19:05 +05:30
rohitwaghchaure
dcb71a61ad [Fix] Payment entry not able to submit (#15859) 2018-11-02 12:12:42 +05:30
Ameya Shenoy
3f32218bc0 Merge branch 'hotfix' 2018-10-31 13:35:59 +00:00
Ameya Shenoy
b4bff7e298 bumped to version 10.1.66 2018-10-31 13:35:58 +00:00
Shreya Shah
41c5fda196 fix(sms-center): Fix db query (#15774) 2018-10-31 18:04:30 +05:30
Shreya Shah
305c82bd8d fix(medical-record): Remove z-index property (#15790) 2018-10-31 18:02:55 +05:30
rohitwaghchaure
cd11bdfdbb [Fix] Supplier wise sales analytics report not showing item details which is added in purchase invoice with update stock (#15869) 2018-10-31 18:02:00 +05:30
Shreya Shah
0c0e49a421 fix: Fix fieldnames in template (#15860) 2018-10-31 18:00:09 +05:30
rohitwaghchaure
3f398d24f3 [Fix] Precision issue, not able to submit the stock entry (#15863) 2018-10-31 17:58:26 +05:30
Ameya Shenoy
d9a82738d0 Merge branch 'hotfix' 2018-10-30 12:48:42 +00:00
Ameya Shenoy
1f7a5dcd07 bumped to version 10.1.65 2018-10-30 12:48:42 +00:00
Shreya Shah
452619c668 fix(report): Return if not list (#15849) 2018-10-30 11:26:01 +05:30
rohitwaghchaure
9d0dba5569 Merge pull request #15851 from frappe/pos-delete-fix
fix: Delete button in POS mobile
2018-10-29 15:19:11 +05:30
Faris Ansari
3df1327b94 fix: Delete button in POS mobile
Delete button was covered by page-actions container
2018-10-29 15:15:10 +05:30
Ameya Shenoy
38eaaade89 Merge branch 'hotfix' 2018-10-23 12:52:46 +00:00
Ameya Shenoy
2a98e59bd4 bumped to version 10.1.64 2018-10-23 12:52:46 +00:00
Ameya Shenoy
03348364e9 Merge pull request #15739 from kennethsequeira/hotfix
Fix for "Improve this page" incorrect link generated in v10 sites
2018-10-23 18:05:25 +05:30
Ameya Shenoy
83fd31973f Merge branch 'hotfix' 2018-10-23 07:58:12 +00:00
Ameya Shenoy
ac64b39562 bumped to version 10.1.63 2018-10-23 07:58:11 +00:00
Ameya Shenoy
c73c576536 Merge pull request #15759 from codingCoffee/salesperson
fix(): fetch correct warehouse for item in report
2018-10-23 13:25:42 +05:30
rohitwaghchaure
034429b34d Merge pull request #15756 from rohitwaghchaure/fixed_allow_edit_rate
[Fix] User able to edit the rate in offline POS even if it has no permissions
2018-10-23 09:43:57 +05:30
Ameya Shenoy
874866e9f9 Merge branch 'hotfix' 2018-10-22 10:34:35 +00:00
Ameya Shenoy
c365ce8f21 bumped to version 10.1.62 2018-10-22 10:34:35 +00:00
Ameya Shenoy
3a11f34355 fix(): fetch correct warehouse for item in report
Fix 'Sales Person-wise Transaction Summary' Report by fetching the
correct Warehouse for the Item fron the respective, Sales Order/Sales
Invoice/ Delivery Note
2018-10-22 10:15:07 +00:00
Nabin Hait
91eac5a7cf fix(report): Optimization for financial statements 2018-10-22 15:05:40 +05:30
Rohit Waghchaure
aef7a6ec44 [Fix] User able to edit the rate in offline POS even if it has no permissions 2018-10-22 13:51:32 +05:30
Ameya Shenoy
6192d24235 Merge branch 'hotfix' 2018-10-19 12:48:17 +00:00
Ameya Shenoy
24fe7286fc bumped to version 10.1.61 2018-10-19 12:48:16 +00:00
Kenneth Sequeira
991c121b57 added source link for ERPNext docs 2018-10-19 14:31:21 +05:30
Kenneth Sequeira
23ec18e3e4 added docs_app variable to point docs to foundation app 2018-10-19 03:28:12 +05:30
Nabin Hait
500ddc94c7 fix(gle): GL Entry for invoices before introduction of rounding_adjustment (#15732) 2018-10-18 16:48:28 +05:30
Ameya Shenoy
bbd8b04012 Merge branch 'hotfix' 2018-10-17 09:04:11 +00:00
Ameya Shenoy
bb1b6b42e2 bumped to version 10.1.60 2018-10-17 09:04:11 +00:00
Shreya Shah
8e71074e1c fix(report): Add column for Item Name (#15702) 2018-10-16 14:36:49 +05:30
Shreya Shah
ff0deedca9 fix(discount-amount): Print hide discount_amount if print without amount (#15704) 2018-10-16 14:34:30 +05:30
deepeshgarg007
4bb90add1d Currency symbol bug fix (#15698) 2018-10-15 19:07:49 +05:30
Nabin Hait
44ec05f79b fix(bom): deadlock issue via bom replace tool (#15694) 2018-10-15 18:56:16 +05:30
Bibin
7844b79274 [Bug-Fix] accounts_receivable.html (#15688)
* Update accounts_receivable.html

In the print format and PDF the total was showing as 0 (Zero) , when I made these changes it fixed the issue

* Update accounts_receivable.html
2018-10-15 18:25:26 +05:30
Nabin Hait
ea75295bb3 Merge branch 'hotfix' 2018-10-15 15:41:25 +05:30
Nabin Hait
d2c643eb0b bumped to version 10.1.59 2018-10-15 16:11:25 +06:00
rohitwaghchaure
94fcb0e9f9 [Enhance] Add user image in the employee from the user (#15680) 2018-10-15 14:57:46 +05:30
rohitwaghchaure
3362d6b948 [Fix] Precision issue in the expense claim (#15678) 2018-10-15 11:07:13 +05:30
Saurabh
75c1682e61 Merge branch 'hotfix' 2018-10-09 17:55:32 +05:30
Saurabh
2dc8972794 bumped to version 10.1.58 2018-10-09 18:25:32 +06:00
Saurabh
f786eccdf9 Merge pull request #15633 from Zlash65/setup-fix
[Minor] Setup Wizard failing fix
2018-10-09 17:49:54 +05:30
Zlash65
a1036ad50b setup wizard failing fix 2018-10-09 17:38:28 +05:30
Shreya Shah
5b34d00bc0 fix(accounts-receivable): Column values in Print and PDF (#15622) 2018-10-08 18:20:51 +05:30
Ameya Shenoy
ee3b788024 Merge branch 'hotfix' 2018-10-08 09:37:37 +00:00
Ameya Shenoy
b509b06edf bumped to version 10.1.57 2018-10-08 09:37:37 +00:00
Zarrar
5fcccda883 [Minor] Supplier Quotation (#15578)
* throw meaningful error if RFQ does not have selected supplier

* Update supplier_quotation.py

* codacy fix
2018-10-08 14:30:53 +05:30
Shreya Shah
4fb9230d16 Add missing method link_to_mrs to buying.js (#15613) 2018-10-08 14:18:03 +05:30
Shreya Shah
37d3686372 fix(setup_taxes): Pop if frappe.message_log (#15615) 2018-10-08 14:17:16 +05:30
Ameya Shenoy
5eafa5a487 Merge branch 'hotfix' 2018-10-05 08:54:46 +00:00
Ameya Shenoy
97dbb4d125 bumped to version 10.1.56 2018-10-05 08:54:46 +00:00
Shreya Shah
17ac38ff29 Enable save before saving to update form after save (#15579) 2018-10-05 11:51:13 +05:30
Ameya Shenoy
65652071ff Merge branch 'hotfix' 2018-10-04 09:11:50 +00:00
Ameya Shenoy
79dc8ac9cc bumped to version 10.1.55 2018-10-04 09:11:50 +00:00
rohitwaghchaure
15e7646edd Merge pull request #15569 from rohitwaghchaure/stock_adjustment_to_cost_of_goods_sold
Book cost of goods sold instead of stock adjustment
2018-10-03 17:36:29 +05:30
Rohit Waghchaure
d1b87ba41c Book cost of goods sold instead of stock adjustment 2018-10-03 16:29:43 +05:30
rohitwaghchaure
a5576f5b21 [Fix] Stock difference between gl entry and stock ledger entry booked in stock adjustment (#15374) 2018-10-03 10:39:50 +05:30
rohitwaghchaure
8976ad5ca1 Merge pull request #15523 from rohitwaghchaure/fix_attendance_tool_issue
[Fix] Attendance tool
2018-10-01 15:07:49 +05:30
Rohit Waghchaure
c7f8b82fff [Fix] Attendance tool 2018-10-01 12:30:58 +05:30
rohitwaghchaure
6b62b86bbf Merge pull request #15545 from rohitwaghchaure/salary_slip_not_creating_because_of_the_date_issue
[Fix] Salary slip
2018-10-01 12:03:26 +05:30
Rohit Waghchaure
8fbf856618 [Fix] Salary slip 2018-10-01 12:00:45 +05:30
Nabin Hait
7d6d678e8d purchase receipt return entry in dashboard 2018-09-26 19:04:11 +05:30
Nabin Hait
c22ba2ec26 fix(sales return): validation message fix 2018-09-26 18:56:45 +05:30
rohitwaghchaure
0cf0ebf08b [Refactored] Asset Depreciation Ledger report based on GL entries (#15415)
* [Refactored] Asset Depreciation Ledger report is based on GL entries

* Provision to make manual JV from the asset if Calculate Depreciation is disabled
2018-09-26 15:24:49 +05:30
Ameya Shenoy
0ff35a852a Merge branch 'hotfix' 2018-09-26 07:26:49 +00:00
Ameya Shenoy
e04431ea5c bumped to version 10.1.54 2018-09-26 07:26:49 +00:00
rohitwaghchaure
fafc277666 [Fix] BOM update tool, too many writes in one request. Please send smaller requests (#15432) 2018-09-25 18:59:20 +05:30
rohitwaghchaure
fe1e4a41e6 Validate negative stock serial number (#15492) 2018-09-25 18:36:32 +05:30
Faris Ansari
7a8c5b0c2c fix(setup wizard): Validate FY dates (#15473) 2018-09-25 18:34:33 +05:30
Saurabh
056ecdca6a Merge branch 'hotfix' 2018-09-20 13:22:36 +05:30
Saurabh
3b281a0a1b bumped to version 10.1.53 2018-09-20 13:52:36 +06:00
rohitwaghchaure
a60ab1af75 [Fix] Salary slip is not saving (#15449) 2018-09-20 13:18:49 +05:30
rohitwaghchaure
550fc695f1 [Fix] Precision issue in the accounts receivable report (#15440) 2018-09-19 19:03:40 +05:30
Zarrar
013493de7a lable for discount_amount should be configurable (#15408) 2018-09-17 11:06:49 +05:30
67 changed files with 805 additions and 262 deletions

View File

@@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
__version__ = '10.1.52'
__version__ = '10.1.75'
def get_default_company(user=None):
'''Get default company for user'''

View File

@@ -791,15 +791,25 @@ frappe.ui.form.on('Payment Entry', {
var write_off_row = $.map(frm.doc["deductions"] || [], function(t) {
return t.account==r.message[account] ? t : null; });
if (!write_off_row.length) {
var row = frm.add_child("deductions");
var row = [];
var difference_amount = flt(frm.doc.difference_amount,
precision("difference_amount"));
if (!write_off_row.length && difference_amount) {
row = frm.add_child("deductions");
row.account = r.message[account];
row.cost_center = r.message["cost_center"];
} else {
var row = write_off_row[0];
row = write_off_row[0];
}
if (row) {
row.amount = flt(row.amount) + difference_amount;
} else {
frappe.msgprint(__("No gain or loss in the exchange rate"))
}
row.amount = flt(row.amount) + flt(frm.doc.difference_amount);
refresh_field("deductions");
frm.events.set_unallocated_amount(frm);

View File

@@ -70,12 +70,14 @@ class PeriodClosingVoucher(AccountsController):
net_pl_balance += flt(acc.balance_in_company_currency)
if net_pl_balance:
cost_center = frappe.db.get_value("Company", self.company, "cost_center")
gl_entries.append(self.get_gl_dict({
"account": self.closing_account_head,
"debit_in_account_currency": abs(net_pl_balance) if net_pl_balance > 0 else 0,
"debit": abs(net_pl_balance) if net_pl_balance > 0 else 0,
"credit_in_account_currency": abs(net_pl_balance) if net_pl_balance < 0 else 0,
"credit": abs(net_pl_balance) if net_pl_balance < 0 else 0
"credit": abs(net_pl_balance) if net_pl_balance < 0 else 0,
"cost_center": cost_center
}))
from erpnext.accounts.general_ledger import make_gl_entries

View File

@@ -72,6 +72,7 @@ class TestPeriodClosingVoucher(unittest.TestCase):
"company": "_Test Company",
"fiscal_year": get_fiscal_year(today(), company="_Test Company")[0],
"posting_date": today(),
"cost_center": "_Test Cost Center - _TC",
"remarks": "test"
})
pcv.insert()

View File

@@ -185,7 +185,8 @@ def get_pricing_rule_for_item(args):
"discount_percentage": 0.0
})
else:
item_details.discount_percentage = pricing_rule.discount_percentage or args.discount_percentage
item_details.discount_percentage = (pricing_rule.get('discount_percentage', 0)
if pricing_rule else args.discount_percentage)
elif args.get('pricing_rule'):
item_details = remove_pricing_rule_for_item(args.get("pricing_rule"), item_details)

View File

@@ -11,12 +11,16 @@ from erpnext.stock.get_item_details import get_item_details
from frappe import MandatoryError
class TestPricingRule(unittest.TestCase):
def setUp(self):
frappe.db.sql("delete from `tabPricing Rule`")
def tearDown(self):
frappe.db.sql("delete from `tabPricing Rule`")
def test_pricing_rule_for_discount(self):
from erpnext.stock.get_item_details import get_item_details
from frappe import MandatoryError
frappe.db.sql("delete from `tabPricing Rule`")
test_record = {
"doctype": "Pricing Rule",
"title": "_Test Pricing Rule",
@@ -88,14 +92,10 @@ class TestPricingRule(unittest.TestCase):
details = get_item_details(args)
self.assertEquals(details.get("discount_percentage"), 15)
frappe.db.sql("delete from `tabPricing Rule`")
def test_pricing_rule_for_margin(self):
from erpnext.stock.get_item_details import get_item_details
from frappe import MandatoryError
frappe.db.sql("delete from `tabPricing Rule`")
test_record = {
"doctype": "Pricing Rule",
"title": "_Test Pricing Rule",
@@ -109,14 +109,14 @@ class TestPricingRule(unittest.TestCase):
"company": "_Test Company"
}
frappe.get_doc(test_record.copy()).insert()
item_price = frappe.get_doc({
"doctype": "Item Price",
"price_list": "_Test Price List 2",
"item_code": "_Test FG Item 2",
"price_list_rate": 100
})
item_price.insert(ignore_permissions=True)
args = frappe._dict({
@@ -136,14 +136,10 @@ class TestPricingRule(unittest.TestCase):
self.assertEquals(details.get("margin_type"), "Percentage")
self.assertEquals(details.get("margin_rate_or_amount"), 10)
frappe.db.sql("delete from `tabPricing Rule`")
def test_pricing_rule_for_variants(self):
from erpnext.stock.get_item_details import get_item_details
from frappe import MandatoryError
frappe.db.sql("delete from `tabPricing Rule`")
if not frappe.db.exists("Item", "Test Variant PRT"):
frappe.get_doc({
"doctype": "Item",
@@ -209,8 +205,6 @@ class TestPricingRule(unittest.TestCase):
self.assertEquals(details.get("discount_percentage"), 17.5)
def test_pricing_rule_for_stock_qty(self):
frappe.db.sql("delete from `tabPricing Rule`")
test_record = {
"doctype": "Pricing Rule",
"title": "_Test Pricing Rule",
@@ -253,24 +247,18 @@ class TestPricingRule(unittest.TestCase):
def test_pricing_rule_with_margin_and_discount(self):
frappe.delete_doc_if_exists('Pricing Rule', '_Test Pricing Rule')
make_pricing_rule(selling=1, margin_type="Percentage", margin_rate_or_amount=10)
make_pricing_rule(selling=1, margin_type="Percentage", margin_rate_or_amount=10, discount_percentage=10)
si = create_sales_invoice(do_not_save=True)
si.items[0].price_list_rate = 1000
si.payment_schedule = []
si.insert(ignore_permissions=True)
item = si.items[0]
self.assertEquals(item.rate, 1100)
self.assertEquals(item.margin_rate_or_amount, 10)
# With discount
item.discount_percentage = 10
si.payment_schedule = []
si.save()
item = si.items[0]
self.assertEquals(item.rate_with_margin, 1100)
self.assertEqual(item.discount_percentage, 10)
self.assertEquals(item.discount_amount, 110)
self.assertEquals(item.rate, 990)
self.assertEquals(item.discount_percentage, 10)
frappe.db.sql("delete from `tabPricing Rule`")
def make_pricing_rule(**args):
args = frappe._dict(args)

View File

@@ -363,7 +363,10 @@ class PurchaseInvoice(BuyingController):
return gl_entries
def make_supplier_gl_entry(self, gl_entries):
grand_total = self.rounded_total or self.grand_total
# Checked both rounding_adjustment and rounded_total
# because rounded_total had value even before introcution of posting GLE based on rounded total
grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
if grand_total:
# Didnot use base_grand_total to book rounding loss gle
grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
@@ -388,16 +391,20 @@ class PurchaseInvoice(BuyingController):
expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
warehouse_account = get_warehouse_account_map()
voucher_wise_stock_value = {}
if self.update_stock:
for d in frappe.get_all('Stock Ledger Entry',
fields = ["voucher_detail_no", "stock_value_difference"], filters={'voucher_no': self.name}):
voucher_wise_stock_value.setdefault(d.voucher_detail_no, d.stock_value_difference)
for item in self.get("items"):
if flt(item.base_net_amount):
account_currency = get_account_currency(item.expense_account)
if self.update_stock and self.auto_accounting_for_stock and item.item_code in stock_items:
val_rate_db_precision = 6 if cint(item.precision("valuation_rate")) <= 6 else 9
# warehouse account
warehouse_debit_amount = flt(flt(item.valuation_rate, val_rate_db_precision)
* flt(item.qty) * flt(item.conversion_factor), item.precision("base_net_amount"))
warehouse_debit_amount = self.make_stock_adjustment_entry(gl_entries,
item, voucher_wise_stock_value, account_currency)
gl_entries.append(
self.get_gl_dict({
@@ -469,6 +476,36 @@ class PurchaseInvoice(BuyingController):
self.negative_expense_to_be_booked += flt(item.item_tax_amount, \
item.precision("item_tax_amount"))
def make_stock_adjustment_entry(self, gl_entries, item, voucher_wise_stock_value, account_currency):
net_amt_precision = item.precision("base_net_amount")
val_rate_db_precision = 6 if cint(item.precision("valuation_rate")) <= 6 else 9
warehouse_debit_amount = flt(flt(item.valuation_rate, val_rate_db_precision)
* flt(item.qty) * flt(item.conversion_factor), net_amt_precision)
# Stock ledger value is not matching with the warehouse amount
if (self.update_stock and voucher_wise_stock_value.get(item.name) and
warehouse_debit_amount != flt(voucher_wise_stock_value.get(item.name), net_amt_precision)):
cost_of_goods_sold_account = self.get_company_default("default_expense_account")
stock_amount = flt(voucher_wise_stock_value.get(item.name), net_amt_precision)
stock_adjustment_amt = warehouse_debit_amount - stock_amount
gl_entries.append(
self.get_gl_dict({
"account": cost_of_goods_sold_account,
"against": item.expense_account,
"debit": stock_adjustment_amt,
"remarks": self.get("remarks") or _("Stock Adjustment"),
"cost_center": item.cost_center,
"project": item.project
}, account_currency)
)
warehouse_debit_amount = stock_amount
return warehouse_debit_amount
def make_tax_gl_entries(self, gl_entries):
# tax table gl entries
valuation_tax = {}

View File

@@ -506,7 +506,7 @@ def save_invoice(doc, name, name_list):
frappe.db.commit()
name_list.append(name)
except Exception:
frappe.log_error(frappe.get_traceback())
frappe.db.rollback()
frappe.log_error(frappe.get_traceback())
return name_list

View File

@@ -589,9 +589,6 @@ class SalesInvoice(SellingController):
def make_gl_entries(self, gl_entries=None, repost_future_gle=True, from_repost=False):
auto_accounting_for_stock = erpnext.is_perpetual_inventory_enabled(self.company)
if not self.grand_total:
return
if not gl_entries:
gl_entries = self.get_gl_entries()
@@ -641,7 +638,9 @@ class SalesInvoice(SellingController):
return gl_entries
def make_customer_gl_entry(self, gl_entries):
grand_total = self.rounded_total or self.grand_total
# Checked both rounding_adjustment and rounded_total
# because rounded_total had value even before introcution of posting GLE based on rounded total
grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
if grand_total:
# Didnot use base_grand_total to book rounding loss gle
grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
@@ -669,9 +668,11 @@ class SalesInvoice(SellingController):
self.get_gl_dict({
"account": tax.account_head,
"against": self.customer,
"credit": flt(tax.base_tax_amount_after_discount_amount),
"credit_in_account_currency": flt(tax.base_tax_amount_after_discount_amount) \
if account_currency==self.company_currency else flt(tax.tax_amount_after_discount_amount),
"credit": flt(tax.base_tax_amount_after_discount_amount,
tax.precision("tax_amount_after_discount_amount")),
"credit_in_account_currency": (flt(tax.base_tax_amount_after_discount_amount,
tax.precision("base_tax_amount_after_discount_amount")) if account_currency==self.company_currency else
flt(tax.tax_amount_after_discount_amount, tax.precision("tax_amount_after_discount_amount"))),
"cost_center": tax.cost_center
}, account_currency)
)
@@ -679,7 +680,7 @@ class SalesInvoice(SellingController):
def make_item_gl_entries(self, gl_entries):
# income account gl entries
for item in self.get("items"):
if flt(item.base_net_amount):
if flt(item.base_net_amount, item.precision("base_net_amount")):
if item.is_fixed_asset:
asset = frappe.get_doc("Asset", item.asset)
@@ -696,9 +697,10 @@ class SalesInvoice(SellingController):
self.get_gl_dict({
"account": item.income_account,
"against": self.customer,
"credit": item.base_net_amount,
"credit_in_account_currency": item.base_net_amount \
if account_currency==self.company_currency else item.net_amount,
"credit": flt(item.base_net_amount, item.precision("base_net_amount")),
"credit_in_account_currency": (flt(item.base_net_amount, item.precision("base_net_amount"))
if account_currency==self.company_currency
else flt(item.net_amount, item.precision("net_amount"))),
"cost_center": item.cost_center
}, account_currency)
)
@@ -769,7 +771,7 @@ class SalesInvoice(SellingController):
def make_write_off_gl_entry(self, gl_entries):
# write off entries, applicable if only pos
if self.write_off_account and self.write_off_amount:
if self.write_off_account and flt(self.write_off_amount, self.precision("write_off_amount")):
write_off_account_currency = get_account_currency(self.write_off_account)
default_cost_center = frappe.db.get_value('Company', self.company, 'cost_center')
@@ -779,9 +781,10 @@ class SalesInvoice(SellingController):
"party_type": "Customer",
"party": self.customer,
"against": self.write_off_account,
"credit": self.base_write_off_amount,
"credit_in_account_currency": self.base_write_off_amount \
if self.party_account_currency==self.company_currency else self.write_off_amount,
"credit": flt(self.base_write_off_amount, self.precision("base_write_off_amount")),
"credit_in_account_currency": (flt(self.base_write_off_amount,
self.precision("base_write_off_amount")) if self.party_account_currency==self.company_currency
else flt(self.write_off_amount, self.precision("write_off_amount"))),
"against_voucher": self.return_against if cint(self.is_return) else self.name,
"against_voucher_type": self.doctype
}, self.party_account_currency)
@@ -790,15 +793,16 @@ class SalesInvoice(SellingController):
self.get_gl_dict({
"account": self.write_off_account,
"against": self.customer,
"debit": self.base_write_off_amount,
"debit_in_account_currency": self.base_write_off_amount \
if write_off_account_currency==self.company_currency else self.write_off_amount,
"debit": flt(self.base_write_off_amount, self.precision("base_write_off_amount")),
"debit_in_account_currency": (flt(self.base_write_off_amount,
self.precision("base_write_off_amount")) if write_off_account_currency==self.company_currency
else flt(self.write_off_amount, self.precision("write_off_amount"))),
"cost_center": self.write_off_cost_center or default_cost_center
}, write_off_account_currency)
)
def make_gle_for_rounding_adjustment(self, gl_entries):
if self.rounding_adjustment:
if flt(self.rounding_adjustment, self.precision("rounding_adjustment")):
round_off_account, round_off_cost_center = \
get_round_off_account_and_cost_center(self.company)
@@ -806,8 +810,10 @@ class SalesInvoice(SellingController):
self.get_gl_dict({
"account": round_off_account,
"against": self.customer,
"credit_in_account_currency": self.rounding_adjustment,
"credit": self.base_rounding_adjustment,
"credit_in_account_currency": flt(self.rounding_adjustment,
self.precision("rounding_adjustment")),
"credit": flt(self.base_rounding_adjustment,
self.precision("base_rounding_adjustment")),
"cost_center": round_off_cost_center,
}
))

View File

@@ -75,7 +75,7 @@
<td class="text-right">{%= format_currency(balance_row[range3]) %}</td>
<td class="text-right">{%= format_currency(balance_row[range4]) %}</td>
<td class="text-right">
{%= format_currency(flt(balance_row[__("Outstanding Amount")]), data[data.length-1]["currency"]) %}
{%= format_currency(flt(balance_row[("outstanding_amount")]), data[data.length-1]["currency"]) %}
</td>
</tr>
<td>{%= __("PDC/LC") %}</td>
@@ -84,7 +84,7 @@
<td></td>
<td></td>
<td class="text-right">
{%= format_currency(flt(balance_row[__("PDC/LC Amount")]), data[data.length-1]["currency"]) %}
{%= format_currency(flt(balance_row[("pdc/lc_amount")]), data[data.length-1]["currency"]) %}
</td>
<tr class="cvs-footer">
<th class="text-left">{%= __("Cheques Required") %}</th>
@@ -93,7 +93,7 @@
<th></th>
<th></th>
<th class="text-right">
{%= format_currency(flt(balance_row[__("Outstanding Amount")]-balance_row[__("PDC/LC Amount")]), data[data.length-1]["currency"]) %}</th>
{%= format_currency(flt(balance_row[("outstanding_amount")]-balance_row[("pdc/lc_amount")]), data[data.length-1]["currency"]) %}</th>
</tr>
</tbody>
@@ -161,26 +161,26 @@
</td>
{% } %}
<td style="text-align: right">
{%= format_currency(data[i]["Invoiced Amount"], data[i]["currency"]) %}</td>
{%= format_currency(data[i]["invoiced_amount"], data[i]["currency"]) %}</td>
{% if(!filters.show_pdc_in_print) { %}
<td style="text-align: right">
{%= format_currency(data[i]["Paid Amount"], data[i]["currency"]) %}</td>
{%= format_currency(data[i]["paid_amount"], data[i]["currency"]) %}</td>
<td style="text-align: right">
{%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["Credit Note"], data[i]["currency"]) : format_currency(data[i]["Debit Note"], data[i]["currency"]) %}</td>
{%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["credit_note"], data[i]["currency"]) : format_currency(data[i]["debit_note"], data[i]["currency"]) %}</td>
{% } %}
<td style="text-align: right">
{%= format_currency(data[i]["Outstanding Amount"], data[i]["currency"]) %}</td>
{%= format_currency(data[i]["outstanding_amount"], data[i]["currency"]) %}</td>
{% if(filters.show_pdc_in_print) { %}
{% if(report.report_name === "Accounts Receivable") { %}
<td style="text-align: right">
{%= data[i][__("Customer LPO")] %}</td>
{%= data[i]["po_no"] %}</td>
{% } %}
<td style="text-align: right">{%= frappe.datetime.str_to_user(data[i][__("PDC/LC Date")]) %}</td>
<td style="text-align: right">{%= data[i][__("PDC/LC Ref")] %}</td>
<td style="text-align: right">{%= format_currency(data[i][__("PDC/LC Amount")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i][__("Remaining Balance")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= frappe.datetime.str_to_user(data[i][("pdc/lc_date")]) %}</td>
<td style="text-align: right">{%= data[i][("pdc/lc_ref")] %}</td>
<td style="text-align: right">{%= format_currency(data[i][("pdc/lc_amount")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i][("remaining_balance")], data[i]["currency"]) %}</td>
{% } %}
{% } else { %}
<td></td>
@@ -189,15 +189,15 @@
{% } %}
<td><b>{%= __("Total") %}</b></td>
<td style="text-align: right">
{%= format_currency(data[i]["Invoiced Amount"], data[i]["currency"] ) %}</td>
{%= format_currency(data[i]["invoiced_amount"], data[i]["currency"] ) %}</td>
{% if(!filters.show_pdc_in_print) { %}
<td style="text-align: right">
{%= format_currency(data[i]["Paid Amount"], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["Credit Note"], data[i]["currency"]) : format_currency(data[i]["Debit Note"], data[i]["currency"]) %} </td>
{%= format_currency(data[i]["paid_amount"], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["credit_note"], data[i]["currency"]) : format_currency(data[i]["debit_note"], data[i]["currency"]) %} </td>
{% } %}
<td style="text-align: right">
{%= format_currency(data[i]["Outstanding Amount"], data[i]["currency"]) %}</td>
{%= format_currency(data[i]["outstanding_amount"], data[i]["currency"]) %}</td>
{% if(filters.show_pdc_in_print) { %}
{% if(report.report_name === "Accounts Receivable") { %}
@@ -205,9 +205,9 @@
{%= data[i][__("Customer LPO")] %}</td>
{% } %}
<td style="text-align: right">{%= frappe.datetime.str_to_user(data[i][__("PDC/LC Date")]) %}</td>
<td style="text-align: right">{%= data[i][__("PDC/LC Ref")] %}</td>
<td style="text-align: right">{%= format_currency(data[i][__("PDC/LC Amount")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i][__("Remaining Balance")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= data[i][("pdc/lc_ref")] %}</td>
<td style="text-align: right">{%= format_currency(data[i][("pdc/lc_amount")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i][("remaining_balance")], data[i]["currency"]) %}</td>
{% } %}
{% } %}
{% } else { %}
@@ -220,7 +220,7 @@
<br> {%= data[i][__("Customer Name")] %}
{% } else if(data[i][__("Supplier Name")] != data[i][__("Supplier")]) { %}
<br> {%= data[i][__("Supplier Name")] %}
{% } %}
{% } %}
{% } %}
<br>{%= __("Remarks") %}:
{%= data[i][__("Remarks")] %}
@@ -228,14 +228,14 @@
{% } else { %}
<td><b>{%= __("Total") %}</b></td>
{% } %}
<td style="text-align: right">{%= format_currency(data[i][__("Total Invoiced Amt")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i][__("Total Paid Amt")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= report.report_name === "Accounts Receivable Summary" ? format_currency(data[i][__("Credit Note Amt")], data[i]["currency"]) : format_currency(data[i][__("Debit Note Amt")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i][__("Total Outstanding Amt")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i][("total_invoiced_amt")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i][("total_paid_amt")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= report.report_name === "Accounts Receivable Summary" ? format_currency(data[i][__("credit_note_amt")], data[i]["currency"]) : format_currency(data[i][__("debit_note_amt")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i][("total_outstanding_amt")], data[i]["currency"]) %}</td>
{% } %}
{% } %}
</tr>
{% } %}
</tbody>
</table>
<p class="text-right text-muted">{{ __("Printed On ") }}{%= dateutil.str_to_user(dateutil.get_datetime_as_string()) %}</p>
<p class="text-right text-muted">{{ __("Printed On ") }}{%= dateutil.str_to_user(dateutil.get_datetime_as_string()) %}</p>

View File

@@ -60,6 +60,7 @@ class ReceivablePayableReport(object):
for label in ("Invoiced Amount", "Paid Amount", credit_or_debit_note, "Outstanding Amount"):
columns.append({
"label": label,
"fieldname": frappe.scrub(label),
"fieldtype": "Currency",
"options": "currency",
"width": 120
@@ -87,25 +88,49 @@ class ReceivablePayableReport(object):
"width": 120
})
columns.append({
columns += [
{
"fieldname": "currency",
"label": _("Currency"),
"fieldtype": "Link",
"options": "Currency",
"width": 100
})
columns += [
_("PDC/LC Date") + ":Date:110",
_("PDC/LC Ref") + ":Data:110",
_("PDC/LC Amount") + ":Currency/currency:130",
_("Remaining Balance") + ":Currency/currency:130"
]
},
{
"fieldname": "pdc/lc_date",
"label": _("PDC/LC Date"),
"fieldtype": "Date",
"width": 110
},
{
"fieldname": "pdc/lc_ref",
"label": _("PDC/LC Ref"),
"fieldtype": "Data",
"width": 110
},
{
"fieldname": "pdc/lc_amount",
"label": _("PDC/LC Amount"),
"fieldtype": "Currency",
"options": "Currency",
"width": 130
},
{
"fieldname": "remaining_balance",
"label": _("Remaining Balance"),
"fieldtype": "Currency",
"options": "Currency",
"width": 130
}]
if args.get('party_type') == 'Customer':
columns += [_("Customer LPO") + ":Data:100"]
columns.append({
"label": _("Customer LPO"),
"fieldtype": "Data",
"fieldname": "po_no",
"width": 100,
})
columns += [_("Delivery Note") + ":Data:100"]
if args.get("party_type") == "Customer":
columns += [
_("Territory") + ":Link/Territory:80",
@@ -134,7 +159,6 @@ class ReceivablePayableReport(object):
data = []
pdc_details = get_pdc_details(args.get("party_type"), self.filters.report_date)
gl_entries_data = self.get_entries_till(self.filters.report_date, args.get("party_type"))
if gl_entries_data:
@@ -253,14 +277,16 @@ class ReceivablePayableReport(object):
for e in self.get_gl_entries_for(gle.party, gle.party_type, gle.voucher_type, gle.voucher_no):
if getdate(e.posting_date) <= report_date and e.name!=gle.name:
amount = flt(e.get(reverse_dr_or_cr)) - flt(e.get(dr_or_cr))
amount = flt(e.get(reverse_dr_or_cr), currency_precision) - flt(e.get(dr_or_cr), currency_precision)
if e.voucher_no not in return_entries:
payment_amount += amount
else:
credit_note_amount += amount
outstanding_amount = flt((flt(gle.get(dr_or_cr)) - flt(gle.get(reverse_dr_or_cr)) \
- payment_amount - credit_note_amount), currency_precision)
outstanding_amount = (flt((flt(gle.get(dr_or_cr), currency_precision)
- flt(gle.get(reverse_dr_or_cr), currency_precision)
- payment_amount - credit_note_amount), currency_precision))
credit_note_amount = flt(credit_note_amount, currency_precision)
return outstanding_amount, credit_note_amount
@@ -422,7 +448,6 @@ def get_pdc_details(party_type, report_date):
and pent.party_type = %s
group by pent.party, pref.reference_name""", (report_date, party_type), as_dict=1):
pdc_details.setdefault((pdc.invoice_no, pdc.party), pdc)
if scrub(party_type):
amount_field = ("jea.debit_in_account_currency"
if party_type == 'Supplier' else "jea.credit_in_account_currency")

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe import _, scrub
from frappe.utils import flt
from erpnext.accounts.report.accounts_receivable.accounts_receivable import ReceivablePayableReport
@@ -18,25 +18,93 @@ class AccountsReceivableSummary(ReceivablePayableReport):
if party_naming_by == "Naming Series":
columns += [ args.get("party_type") + " Name::140"]
credit_debit_label = _("Credit Note Amt") if args.get('party_type') == 'Customer' else _("Debit Note Amt")
credit_debit_label = "Credit Note Amt" if args.get('party_type') == 'Customer' else "Debit Note Amt"
columns += [{
"label": _("Total Invoiced Amt"),
"fieldname": "total_invoiced_amt",
"fieldtype": "Currency",
"options": "currency",
"width": 100
},
{
"label": _("Total Paid Amt"),
"fieldname": "total_paid_amt",
"fieldtype": "Currency",
"options": "currency",
"width": 100
}]
columns += [
_("Total Invoiced Amt") + ":Currency/currency:140",
_("Total Paid Amt") + ":Currency/currency:140",
credit_debit_label + ":Currency/currency:140",
_("Total Outstanding Amt") + ":Currency/currency:160",
"0-" + str(self.filters.range1) + ":Currency/currency:100",
str(self.filters.range1) + "-" + str(self.filters.range2) + ":Currency/currency:100",
str(self.filters.range2) + "-" + str(self.filters.range3) + ":Currency/currency:100",
str(self.filters.range3) + _("-Above") + ":Currency/currency:100"]
{
"label": _(credit_debit_label),
"fieldname": scrub(credit_debit_label),
"fieldtype": "Currency",
"options": "currency",
"width": 140
},
{
"label": _("Total Outstanding Amt"),
"fieldname": "total_outstanding_amt",
"fieldtype": "Currency",
"options": "currency",
"width": 160
},
{
"label": _("0-" + str(self.filters.range1)),
"fieldname": scrub("0-" + str(self.filters.range1)),
"fieldtype": "Currency",
"options": "currency",
"width": 160
},
{
"label": _(str(self.filters.range1) + "-" + str(self.filters.range2)),
"fieldname": scrub(str(self.filters.range1) + "-" + str(self.filters.range2)),
"fieldtype": "Currency",
"options": "currency",
"width": 160
},
{
"label": _(str(self.filters.range2) + "-" + str(self.filters.range3)),
"fieldname": scrub(str(self.filters.range2) + "-" + str(self.filters.range3)),
"fieldtype": "Currency",
"options": "currency",
"width": 160
},
{
"label": _(str(self.filters.range3) + _("-Above")),
"fieldname": scrub(str(self.filters.range3) + _("-Above")),
"fieldtype": "Currency",
"options": "currency",
"width": 160
}
]
if args.get("party_type") == "Customer":
columns += [
_("Territory") + ":Link/Territory:80",
_("Customer Group") + ":Link/Customer Group:120"
]
columns += [{
"label": _("Territory"),
"fieldname": "territory",
"fieldtype": "Link",
"options": "Territory",
"width": 80
},
{
"label": _("Customer Group"),
"fieldname": "customer_group",
"fieldtype": "Link",
"options": "Customer Group",
"width": 80
}]
if args.get("party_type") == "Supplier":
columns += [_("Supplier Type") + ":Link/Supplier Type:80"]
columns += [{
"label": _("Supplier Group"),
"fieldname": "supplier_group",
"fieldtype": "Link",
"options": "Supplier Group",
"width": 80
}]
columns.append({
"fieldname": "currency",
"label": _("Currency"),
@@ -67,7 +135,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
row += [self.get_territory(party), self.get_customer_group(party)]
if args.get("party_type") == "Supplier":
row += [self.get_supplier_type(party)]
row.append(party_dict.currency)
data.append(row)
@@ -91,7 +159,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
for k in party_total[d.party].keys():
if k != "currency":
party_total[d.party][k] += flt(d.get(k, 0))
party_total[d.party].currency = d.currency
return party_total

View File

@@ -3,47 +3,75 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import flt
from frappe import _
def execute(filters=None):
columns, data = get_columns(), get_data(filters)
return columns, data
def get_data(filters):
data = frappe.db.sql("""
select
a.name as asset, a.asset_category, a.status,
a.depreciation_method, a.purchase_date, a.gross_purchase_amount,
ds.schedule_date as depreciation_date, ds.depreciation_amount,
ds.accumulated_depreciation_amount,
(a.gross_purchase_amount - ds.accumulated_depreciation_amount) as amount_after_depreciation,
ds.journal_entry as depreciation_entry
from
`tabAsset` a, `tabDepreciation Schedule` ds
where
a.name = ds.parent
and a.docstatus=1
and ifnull(ds.journal_entry, '') != ''
and ds.schedule_date between %(from_date)s and %(to_date)s
and a.company = %(company)s
{conditions}
order by
a.name asc, ds.schedule_date asc
""".format(conditions=get_filter_conditions(filters)), filters, as_dict=1)
return data
def get_filter_conditions(filters):
conditions = ""
data = []
depreciation_accounts = frappe.db.sql_list(""" select name from tabAccount
where ifnull(account_type, '') = 'Depreciation' """)
filters_data = [["company", "=", filters.get('company')],
["posting_date", ">=", filters.get('from_date')],
["posting_date", "<=", filters.get('to_date')],
["against_voucher_type", "=", "Asset"],
["account", "in", depreciation_accounts]]
if filters.get("asset"):
conditions += " and a.name = %(asset)s"
filters_data.append(["against_voucher", "=", filters.get("asset")])
if filters.get("asset_category"):
conditions += " and a.asset_category = %(asset_category)s"
return conditions
assets = frappe.db.sql_list("""select name from tabAsset
where asset_category = %s and docstatus=1""", filters.get("asset_category"))
filters_data.append(["against_voucher", "in", assets])
gl_entries = frappe.get_all('GL Entry',
filters= filters_data,
fields = ["against_voucher", "debit_in_account_currency as debit", "voucher_no", "posting_date"],
order_by= "against_voucher, posting_date")
if not gl_entries:
return data
assets = [d.against_voucher for d in gl_entries]
assets_details = get_assets_details(assets)
for d in gl_entries:
asset_data = assets_details.get(d.against_voucher)
if not asset_data.get("accumulated_depreciation_amount"):
asset_data.accumulated_depreciation_amount = d.debit
else:
asset_data.accumulated_depreciation_amount += d.debit
row = frappe._dict(asset_data)
row.update({
"depreciation_amount": d.debit,
"depreciation_date": d.posting_date,
"amount_after_depreciation": (flt(row.gross_purchase_amount) -
flt(row.accumulated_depreciation_amount)),
"depreciation_entry": d.voucher_no
})
data.append(row)
return data
def get_assets_details(assets):
assets_details = {}
fields = ["name as asset", "gross_purchase_amount",
"asset_category", "status", "depreciation_method", "purchase_date"]
for d in frappe.get_all("Asset", fields = fields, filters = {'name': ('in', assets)}):
assets_details.setdefault(d.asset, d)
return assets_details
def get_columns():
return [
{

View File

@@ -306,19 +306,20 @@ def set_gl_entries_by_account(company, from_date, to_date, root_lft, root_rgt, f
additional_conditions = get_additional_conditions(from_date, ignore_closing_entries, filters)
accounts = frappe.db.sql_list("""select name from `tabAccount`
where lft >= %s and rgt <= %s""", (root_lft, root_rgt))
additional_conditions += " and account in ('{}')"\
.format("', '".join([frappe.db.escape(d) for d in accounts]))
gl_entries = frappe.db.sql("""select posting_date, account, debit, credit, is_opening, fiscal_year from `tabGL Entry`
where company=%(company)s
{additional_conditions}
and posting_date <= %(to_date)s
and account in (select name from `tabAccount`
where lft >= %(lft)s and rgt <= %(rgt)s)
order by account, posting_date""".format(additional_conditions=additional_conditions),
{
"company": company,
"from_date": from_date,
"to_date": to_date,
"lft": root_lft,
"rgt": root_rgt
},
as_dict=True)

View File

@@ -16,7 +16,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
if not filters: filters = {}
columns = get_columns(additional_table_columns)
company_currency = erpnext.get_company_currency(filters.company)
company_currency = erpnext.get_company_currency(filters.get('company'))
item_list = get_items(filters, additional_query_columns)
if item_list:
@@ -54,7 +54,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
]
row += [(d.base_net_rate * d.qty)/d.stock_qty, d.base_net_amount] \
if d.stock_uom != d.uom else [d.base_net_rate, d.base_net_amount]
if d.stock_uom != d.uom and d.stock_qty != 0 else [d.base_net_rate, d.base_net_amount]
total_tax = 0
for tax in tax_columns:

View File

@@ -67,11 +67,33 @@ frappe.ui.form.on('Asset', {
frm.trigger("create_asset_maintenance");
}, __("Make"));
}
if (!frm.doc.calculate_depreciation) {
frm.add_custom_button(__("Depreciation Entry"), function() {
frm.trigger("make_journal_entry");
}, __("Make"));
}
frm.page.set_inner_btn_group_as_primary(__("Make"));
frm.trigger("setup_chart");
}
},
make_journal_entry: function(frm) {
frappe.call({
method: "erpnext.assets.doctype.asset.asset.make_journal_entry",
args: {
asset_name: frm.doc.name
},
callback: function(r) {
if (r.message) {
var doclist = frappe.model.sync(r.message);
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
}
}
})
},
setup_chart: function(frm) {
var x_intervals = [frm.doc.purchase_date];
var asset_values = [frm.doc.gross_purchase_amount];

View File

@@ -283,3 +283,34 @@ def get_item_details(item_code):
})
return ret
@frappe.whitelist()
def make_journal_entry(asset_name):
asset = frappe.get_doc("Asset", asset_name)
fixed_asset_account, accumulated_depreciation_account, depreciation_expense_account = \
get_depreciation_accounts(asset)
depreciation_cost_center, depreciation_series = frappe.db.get_value("Company", asset.company,
["depreciation_cost_center", "series_for_depreciation_entry"])
depreciation_cost_center = asset.cost_center or depreciation_cost_center
je = frappe.new_doc("Journal Entry")
je.voucher_type = "Depreciation Entry"
je.naming_series = depreciation_series
je.company = asset.company
je.remark = "Depreciation Entry against asset {0}".format(asset_name)
je.append("accounts", {
"account": depreciation_expense_account,
"reference_type": "Asset",
"reference_name": asset.name,
"cost_center": depreciation_cost_center
})
je.append("accounts", {
"account": accumulated_depreciation_account,
"reference_type": "Asset",
"reference_name": asset.name
})
return je

View File

@@ -5,13 +5,13 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import flt, today, getdate
from frappe.utils import flt, today, getdate, cint
def post_depreciation_entries(date=None):
# Return if automatic booking of asset depreciation is disabled
if not frappe.db.get_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically"):
if not cint(frappe.db.get_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically")):
return
if not date:
date = today()
for asset in get_depreciable_assets(date):

View File

@@ -60,7 +60,12 @@ class SupplierQuotation(BuyingController):
for rfq in rfq_list:
doc = frappe.get_doc('Request for Quotation', rfq)
doc_sup = frappe.get_all('Request for Quotation Supplier', filters=
{'parent': doc.name, 'supplier': self.supplier}, fields=['name', 'quote_status'])[0]
{'parent': doc.name, 'supplier': self.supplier}, fields=['name', 'quote_status'])
doc_sup = doc_sup[0] if doc_sup else None
if not doc_sup:
frappe.throw(_("Supplier {0} not found in {1}").format(self.supplier,
"<a href='desk#Form/Request for Quotation/{0}'> Request for Quotation {0} </a>".format(doc.name)))
quote_status = _('Received')
for item in doc.items:
@@ -152,4 +157,4 @@ def make_quotation(source_name, target_doc=None):
}
}, target_doc)
return doclist
return doclist

View File

@@ -1,3 +1,3 @@
from __future__ import unicode_literals
source_link = "https://github.com/frappe/erpnext"
source_link = "https://github.com/erpnext/foundation"

View File

@@ -10,6 +10,7 @@ from erpnext.accounts.party import get_party_details
from erpnext.stock.get_item_details import get_conversion_factor
from erpnext.buying.utils import validate_for_items, update_last_purchase_rate
from erpnext.stock.stock_ledger import get_valuation_rate
from frappe.contacts.doctype.address.address import get_address_display
from erpnext.controllers.stock_controller import StockController
@@ -39,6 +40,7 @@ class BuyingController(StockController):
self.set_qty_as_per_stock_uom()
self.validate_stock_or_nonstock_items()
self.validate_warehouse()
self.set_supplier_address()
if self.doctype=="Purchase Invoice":
self.validate_purchase_receipt_if_update_stock()
@@ -96,6 +98,16 @@ class BuyingController(StockController):
if not d.cost_center and lc_voucher_data and lc_voucher_data[0][1]:
d.db_set('cost_center', lc_voucher_data[0][1])
def set_supplier_address(self):
address_dict = {
'supplier_address': 'address_display',
'shipping_address': 'shipping_address_display'
}
for address_field, address_display_field in address_dict.items():
if self.get(address_field):
self.set(address_display_field, get_address_display(self.get(address_field)))
def set_total_in_words(self):
from frappe.utils import money_in_words
if self.meta.get_field("base_in_words"):

View File

@@ -139,7 +139,7 @@ def validate_quantity(doc, args, ref, valid_items, already_returned_items):
.format(args.item_code), StockOverReturnError)
elif abs(current_stock_qty) > max_returnable_qty:
frappe.throw(_("Row # {0}: Cannot return more than {1} for Item {2}")
.format(args.idx, reference_qty, args.item_code), StockOverReturnError)
.format(args.idx, max_returnable_qty, args.item_code), StockOverReturnError)
def get_ref_item_dict(valid_items, ref_item_row):
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos

View File

@@ -8,6 +8,7 @@ from frappe import _, throw
from erpnext.stock.get_item_details import get_bin_details
from erpnext.stock.utils import get_incoming_rate
from erpnext.stock.get_item_details import get_conversion_factor
from frappe.contacts.doctype.address.address import get_address_display
from erpnext.controllers.stock_controller import StockController
@@ -40,6 +41,7 @@ class SellingController(StockController):
self.validate_selling_price()
self.set_qty_as_per_stock_uom()
self.set_po_nos()
self.set_customer_address()
check_active_sales_items(self)
def set_missing_values(self, for_validate=False):
@@ -344,6 +346,17 @@ class SellingController(StockController):
po_nos = frappe.get_all('Sales Order', 'po_no', filters = {'name': ('in', sales_orders)})
self.po_no = ', '.join(list(set([d.po_no for d in po_nos if d.po_no])))
def set_customer_address(self):
address_dict = {
'customer_address': 'address_display',
'shipping_address_name': 'shipping_address',
'company_address': 'company_address_display'
}
for address_field, address_display_field in address_dict.items():
if self.get(address_field):
self.set(address_display_field, get_address_display(self.get(address_field)))
def validate_items(self):
# validate items to see if they have is_sales_item enabled
from erpnext.controllers.buying_controller import validate_item_type

View File

@@ -66,8 +66,11 @@ class calculate_taxes_and_totals(object):
if item.doctype in ['Quotation Item', 'Sales Order Item', 'Delivery Note Item', 'Sales Invoice Item']:
item.rate_with_margin, item.base_rate_with_margin = self.calculate_margin(item)
item.rate = flt(item.rate_with_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate"))\
if item.rate_with_margin > 0 else item.rate
if flt(item.rate_with_margin) > 0:
item.rate = flt(item.rate_with_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate"))
item.discount_amount = item.rate_with_margin - item.rate
elif flt(item.price_list_rate) > 0:
item.discount_amount = item.price_list_rate - item.rate
item.net_rate = item.rate
item.amount = flt(item.rate * item.qty, item.precision("amount"))

View File

@@ -50,6 +50,12 @@ frappe.ui.form.on("Assessment Result", {
frappe.ui.form.on("Assessment Result Detail", {
score: function(frm, cdt, cdn) {
var d = locals[cdt][cdn];
if(!d.maximum_score || !frm.doc.grading_scale) {
d.score = "";
frappe.throw(__("Please fill in all the details to generate Assessment Result."));
}
if (d.score > d.maximum_score) {
frappe.throw(__("Score cannot be greater than Maximum Score"));
}

View File

@@ -73,6 +73,7 @@ def get_attendance_list(from_date, to_date, student_group, students_list):
return att_map
def get_students_with_leave_application(from_date, to_date, students_list):
if not students_list: return
leave_applications = frappe.db.sql("""
select student, from_date, to_date
from `tabStudent Leave Application`

View File

@@ -111,6 +111,7 @@ frappe.ui.form.on('Patient Appointment', {
frm.set_value('appointment_time', selected_slot);
frm.set_value('duration', data.time_per_appointment);
d.hide();
frm.enable_save();
frm.save();
}
});

View File

@@ -14,10 +14,6 @@
margin-bottom: -4px;
}
.medical_record-row > * {
z-index: -999;
}
.date-indicator {
background:none;
font-size:12px;

View File

@@ -15,6 +15,8 @@ develop_version = '10.x.x-develop'
error_report_email = "support@erpnext.com"
docs_app = "foundation"
app_include_js = "assets/js/erpnext.min.js"
app_include_css = "assets/css/erpnext.css"
web_include_js = "assets/js/erpnext-web.min.js"

View File

@@ -45,14 +45,21 @@ class Employee(NestedSet):
self.validate_prefered_email()
if self.user_id:
self.validate_for_enabled_user_id()
self.validate_duplicate_user_id()
self.validate_user_details()
else:
existing_user_id = frappe.db.get_value("Employee", self.name, "user_id")
if existing_user_id:
frappe.permissions.remove_user_permission(
"Employee", self.name, existing_user_id)
def validate_user_details(self):
data = frappe.db.get_value('User',
self.user_id, ['enabled', 'user_image'], as_dict=1)
self.image = data.get("user_image")
self.validate_for_enabled_user_id(data.get("enabled", 0))
self.validate_duplicate_user_id()
def update_nsm_model(self):
frappe.utils.nestedset.update_nsm(self)
@@ -133,10 +140,10 @@ class Employee(NestedSet):
if self.status == 'Left' and not self.relieving_date:
throw(_("Please enter relieving date."))
def validate_for_enabled_user_id(self):
def validate_for_enabled_user_id(self, enabled):
if not self.status == 'Active':
return
enabled = frappe.db.get_value("User", self.user_id, "enabled")
if enabled is None:
frappe.throw(_("User {0} does not exist").format(self.user_id))
if enabled == 0:

View File

@@ -58,7 +58,7 @@ class EmployeeAdvance(Document):
select sum(ifnull(allocated_amount, 0))
from `tabExpense Claim Advance`
where employee_advance = %s and docstatus=1 and allocated_amount > 0
""", self.name)[0][0]
""", self.name)[0][0] or 0
frappe.db.set_value("Employee Advance", self.name, "claimed_amount", claimed_amount)

View File

@@ -224,10 +224,11 @@ class ExpenseClaim(AccountsController):
self.total_advance_amount += flt(d.allocated_amount)
if self.total_advance_amount:
if flt(self.total_advance_amount) > flt(self.total_claimed_amount):
precision = self.precision("total_advance_amount")
if flt(self.total_advance_amount, precision) > flt(self.total_claimed_amount, precision):
frappe.throw(_("Total advance amount cannot be greater than total claimed amount"))
if self.total_sanctioned_amount \
and flt(self.total_advance_amount) > flt(self.total_sanctioned_amount):
and flt(self.total_advance_amount, precision) > flt(self.total_sanctioned_amount, precision):
frappe.throw(_("Total advance amount cannot be greater than total sanctioned amount"))
def validate_sanctioned_amount(self):

View File

@@ -113,16 +113,14 @@ frappe.ui.form.on('Salary Slip Timesheet', {
// Get leave details
//---------------------------------------------------------------------
var get_emp_and_leave_details = function(doc, dt, dn) {
if(!doc.start_date){
return frappe.call({
method: 'get_emp_and_leave_details',
doc: locals[dt][dn],
callback: function(r, rt) {
cur_frm.refresh();
calculate_all(doc, dt, dn);
}
});
}
return frappe.call({
method: 'get_emp_and_leave_details',
doc: locals[dt][dn],
callback: function(r, rt) {
cur_frm.refresh();
calculate_all(doc, dt, dn);
}
});
}
cur_frm.cscript.employee = function(doc,dt,dn){

View File

@@ -181,7 +181,8 @@ class SalarySlip(TransactionBase):
if len(st_name) > 1:
frappe.msgprint(_("Multiple active Salary Structures found for employee {0} for the given dates")
.format(self.employee), title=_('Warning'))
return st_name and st_name[0][0] or ''
self.salary_structure = st_name and st_name[0][0] or ''
return self.salary_structure
else:
self.salary_structure = None
frappe.msgprint(_("No active or default Salary Structure found for employee {0} for the given dates")

View File

@@ -5,7 +5,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cstr, add_days, date_diff
from frappe.utils import cstr, add_days, date_diff, getdate
from frappe import _
from frappe.utils.csvutils import UnicodeWriter
from frappe.model.document import Document
@@ -48,8 +48,9 @@ def add_data(w, args):
for employee in employees:
existing_attendance = {}
if existing_attendance_records \
and tuple([date, employee.name]) in existing_attendance_records:
existing_attendance = existing_attendance_records[tuple([date, employee.name])]
and tuple([getdate(date), employee.name]) in existing_attendance_records:
existing_attendance = existing_attendance_records[tuple([getdate(date), employee.name])]
row = [
existing_attendance and existing_attendance.name or "",
employee.name, employee.employee_name, date,
@@ -114,6 +115,7 @@ def upload():
if not row: continue
row_idx = i + 5
d = frappe._dict(zip(columns, row))
d["doctype"] = "Attendance"
if d.name:
d["docstatus"] = frappe.db.get_value("Attendance", d.name, "docstatus")
@@ -121,6 +123,8 @@ def upload():
try:
check_record(d)
ret.append(import_doc(d, "Attendance", 1, row_idx, submit=True))
except AttributeError:
pass
except Exception as e:
error = True
ret.append('Error for row (#%d) %s : %s' % (row_idx,

View File

@@ -354,7 +354,8 @@ class BOM(WebsiteGenerator):
bom_list = self.traverse_tree(bom_list)
for bom in bom_list:
bom_obj = frappe.get_doc("BOM", bom)
bom_obj.on_update()
bom_obj.check_recursion()
bom_obj.update_exploded_items()
return bom_list

View File

@@ -16,16 +16,23 @@ class BOMUpdateTool(Document):
self.update_new_bom()
bom_list = self.get_parent_boms(self.new_bom)
updated_bom = []
for bom in bom_list:
bom_obj = frappe.get_doc("BOM", bom)
bom_obj.get_doc_before_save()
updated_bom = bom_obj.update_cost_and_exploded_items(updated_bom)
bom_obj.calculate_cost()
bom_obj.update_parent_cost()
bom_obj.db_update()
if (getattr(bom_obj.meta, 'track_changes', False)
and bom_obj._doc_before_save and not bom_obj.flags.ignore_version):
bom_obj.save_version()
try:
bom_obj = frappe.get_doc("BOM", bom)
bom_obj.get_doc_before_save()
updated_bom = bom_obj.update_cost_and_exploded_items(updated_bom)
bom_obj.calculate_cost()
bom_obj.update_parent_cost()
bom_obj.db_update()
if (getattr(bom_obj.meta, 'track_changes', False)
and bom_obj._doc_before_save and not bom_obj.flags.ignore_version):
bom_obj.save_version()
frappe.db.commit()
except Exception:
frappe.db.rollback()
frappe.log_error(frappe.get_traceback())
def validate_bom(self):
if cstr(self.current_bom) == cstr(self.new_bom):
@@ -55,7 +62,7 @@ class BOMUpdateTool(Document):
bom_list.append(d[0])
self.get_parent_boms(d[0], bom_list)
return bom_list
return list(set(bom_list))
@frappe.whitelist()
def enqueue_replace_bom(args):

View File

@@ -505,4 +505,6 @@ erpnext.patches.v10_0.update_status_in_purchase_receipt
erpnext.patches.v10_0.update_address_template_for_india
erpnext.patches.v10_0.set_discount_amount
erpnext.patches.v10_0.recalculate_gross_margin_for_project
erpnext.patches.v10_0.delete_hub_documents
erpnext.patches.v10_0.delete_hub_documents
erpnext.patches.v10_0.update_user_image_in_employee
erpnext.patches.v10_0.repost_gle_for_purchase_receipts_with_rejected_items

View File

@@ -0,0 +1,32 @@
# Copyright (c) 2017, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe, erpnext
def execute():
for company in frappe.get_all("Company"):
if not erpnext.is_perpetual_inventory_enabled(company.name):
continue
acc_frozen_upto = frappe.db.get_value("Accounts Settings", None, "acc_frozen_upto") or "1900-01-01"
pr_with_rejected_warehouse = frappe.db.sql("""
select pr.name
from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pr_item
where pr.name = pr_item.parent
and pr.posting_date > %s
and pr.docstatus=1
and pr.company = %s
and pr_item.rejected_qty > 0
""", (acc_frozen_upto, company.name), as_dict=1)
for d in pr_with_rejected_warehouse:
doc = frappe.get_doc("Purchase Receipt", d.name)
doc.docstatus = 2
doc.make_gl_entries_on_cancel(repost_future_gle=False)
# update gl entries for submit state of PR
doc.docstatus = 1
doc.make_gl_entries(repost_future_gle=False)

View File

@@ -0,0 +1,19 @@
# Copyright (c) 2017, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
frappe.reload_doc('hr', 'doctype', 'employee')
frappe.db.sql("""
UPDATE
`tabEmployee`, `tabUser`
SET
`tabEmployee`.image = `tabUser`.user_image
WHERE
`tabEmployee`.user_id = `tabUser`.name and
`tabEmployee`.user_id is not null and
`tabEmployee`.user_id != '' and `tabEmployee`.image is null
""")

View File

@@ -254,13 +254,13 @@ class Project(Document):
self.total_purchase_cost = total_purchase_cost and total_purchase_cost[0][0] or 0
def update_sales_amount(self):
total_sales_amount = frappe.db.sql("""select sum(base_grand_total)
total_sales_amount = frappe.db.sql("""select sum(base_net_total)
from `tabSales Order` where project = %s and docstatus=1""", self.name)
self.total_sales_amount = total_sales_amount and total_sales_amount[0][0] or 0
def update_billed_amount(self):
total_billed_amount = frappe.db.sql("""select sum(base_grand_total)
total_billed_amount = frappe.db.sql("""select sum(base_net_total)
from `tabSales Invoice` where project = %s and docstatus=1""", self.name)
self.total_billed_amount = total_billed_amount and total_billed_amount[0][0] or 0

View File

@@ -346,6 +346,11 @@ body[data-route="pos"] .btn-more {
body[data-route="pos"] .collapse-btn {
cursor: pointer;
}
@media (max-width: 767px) {
body[data-route="pos"] .page-actions {
max-width: 110px;
}
}
.price-info {
position: absolute;
left: 0;

View File

@@ -227,6 +227,69 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
tc_name: function() {
this.get_terms();
},
link_to_mrs: function() {
var my_items = [];
for (var i in cur_frm.doc.items) {
if(!cur_frm.doc.items[i].material_request){
my_items.push(cur_frm.doc.items[i].item_code);
}
}
frappe.call({
method: "erpnext.buying.utils.get_linked_material_requests",
args:{
items: my_items
},
callback: function(r) {
if(!r.message) {
frappe.throw(__("No pending Material Requests found to link for the given items."))
}
else {
var i = 0;
var item_length = cur_frm.doc.items.length;
while (i < item_length) {
var qty = cur_frm.doc.items[i].qty;
(r.message[0] || []).forEach(function(d) {
if (d.qty > 0 && qty > 0 && cur_frm.doc.items[i].item_code == d.item_code && !cur_frm.doc.items[i].material_request_item)
{
cur_frm.doc.items[i].material_request = d.mr_name;
cur_frm.doc.items[i].material_request_item = d.mr_item;
var my_qty = Math.min(qty, d.qty);
qty = qty - my_qty;
d.qty = d.qty - my_qty;
cur_frm.doc.items[i].stock_qty = my_qty*cur_frm.doc.items[i].conversion_factor;
cur_frm.doc.items[i].qty = my_qty;
frappe.msgprint("Assigning " + d.mr_name + " to " + d.item_code + " (row " + cur_frm.doc.items[i].idx + ")");
if (qty > 0)
{
frappe.msgprint("Splitting " + qty + " units of " + d.item_code);
var newrow = frappe.model.add_child(cur_frm.doc, cur_frm.doc.items[i].doctype, "items");
item_length++;
for (var key in cur_frm.doc.items[i])
{
newrow[key] = cur_frm.doc.items[i][key];
}
newrow.idx = item_length;
newrow["stock_qty"] = newrow.conversion_factor*qty;
newrow["qty"] = qty;
newrow["material_request"] = "";
newrow["material_request_item"] = "";
}
}
});
i++;
}
refresh_field("items");
//cur_frm.save();
}
}
});
}
});

View File

@@ -10,9 +10,8 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
+ flt(item.price_list_rate) * ( flt(item.margin_rate_or_amount) / 100);
} else {
item.rate_with_margin = flt(item.price_list_rate) + flt(item.margin_rate_or_amount);
item.base_rate_with_margin = flt(item.rate_with_margin) * flt(this.frm.doc.conversion_rate);
}
item.base_rate_with_margin = flt(item.rate_with_margin) * flt(this.frm.doc.conversion_rate);
item.rate = flt(item.rate_with_margin , precision("rate", item));
if(item.discount_percentage){

View File

@@ -33,7 +33,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
item.margin_rate_or_amount = 0;
item.rate_with_margin = 0;
}
item.base_rate_with_margin = item.rate_with_margin * flt(frm.doc.conversion_rate);
cur_frm.cscript.set_gross_profit(item);
cur_frm.cscript.calculate_taxes_and_totals();

View File

@@ -73,7 +73,7 @@
{% for(var j=i*3; j
<(i+1)*3; j++) { %} <button type="button" class="btn btn-default numeric-keypad" val="{{j+1}}">{{j+1}}</button>
{% } %}
<button type="button" {% if((!allow_user_to_edit_rate && chartData[i] == __("Price")) || (!allow_user_to_edit_discount && chartData[i] == __("Disc"))) { %} disabled {% } %} id="pos-item-{{ chartData[i].toLowerCase() }}" class="btn text-center btn-default numeric-keypad pos-operation">{{ __(chartData[i]) }}</button>
<button type="button" {% if((!allow_user_to_edit_rate && __(chartData[i]) == __("Price")) || (!allow_user_to_edit_discount && __(chartData[i]) == __("Disc"))) { %} disabled {% } %} id="pos-item-{{ chartData[i].toLowerCase() }}" class="btn text-center btn-default numeric-keypad pos-operation">{{ __(chartData[i]) }}</button>
</div>
{% } %}
<div class="row text-right">

View File

@@ -97,6 +97,9 @@ erpnext.setup.slides_settings = [
if (!this.values.company_abbr) {
return false;
}
if (this.values.company_abbr.length > 5) {
return false;
}
return true;
}
},
@@ -138,10 +141,15 @@ erpnext.setup.slides_settings = [
validate: function () {
// validate fiscal year start and end dates
if (this.values.fy_start_date == 'Invalid date' || this.values.fy_end_date == 'Invalid date') {
const invalid = this.values.fy_start_date == 'Invalid date' ||
this.values.fy_end_date == 'Invalid date';
const start_greater_than_end = this.values.fy_start_date > this.values.fy_end_date;
if (invalid || start_greater_than_end) {
frappe.msgprint(__("Please enter valid Financial Year Start and End Dates"));
return false;
}
return true;
},

View File

@@ -320,7 +320,7 @@ frappe.ui.form.ItemQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
["attribute_value", "like", e.target.value + "%"]
],
fields: ["attribute_value"],
parent: "Item"
parent: "Item Attribute"
},
callback: function(r) {
if (r.message) {

View File

@@ -412,6 +412,12 @@ body[data-route="pos"] {
.collapse-btn {
cursor: pointer;
}
@media (max-width: @screen-xs) {
.page-actions {
max-width: 110px;
}
}
}
.price-info {

View File

@@ -15,19 +15,24 @@ class SMSCenter(Document):
def create_receiver_list(self):
rec, where_clause = '', ''
if self.send_to == 'All Customer Contact':
where_clause = self.customer and " and customer = '%s'" % \
self.customer.replace("'", "\'") or " and ifnull(customer, '') != ''"
where_clause = " and dl.link_doctype = 'Customer'"
if self.customer:
where_clause += " and dl.link_name = '%s'" % \
self.customer.replace("'", "\'") or " and ifnull(dl.link_name, '') != ''"
if self.send_to == 'All Supplier Contact':
where_clause = self.supplier and " and supplier = '%s'" % \
self.supplier.replace("'", "\'") or " and ifnull(supplier, '') != ''"
where_clause = " and dl.link_doctype = 'Supplier'"
if self.supplier:
where_clause += " and dl.link_name = '%s'" % \
self.supplier.replace("'", "\'") or " and ifnull(dl.link_name, '') != ''"
if self.send_to == 'All Sales Partner Contact':
where_clause = self.sales_partner and " and sales_partner = '%s'" % \
self.sales_partner.replace("'", "\'") or " and ifnull(sales_partner, '') != ''"
where_clause = " and dl.link_doctype = 'Sales Partner'"
if self.sales_partner:
where_clause += "and dl.link_name = '%s'" % \
self.sales_partner.replace("'", "\'") or " and ifnull(dl.link_name, '') != ''"
if self.send_to in ['All Contact', 'All Customer Contact', 'All Supplier Contact', 'All Sales Partner Contact']:
rec = frappe.db.sql("""select CONCAT(ifnull(first_name,''), ' ', ifnull(last_name,'')),
mobile_no from `tabContact` where ifnull(mobile_no,'')!='' and
docstatus != 2 %s""" % where_clause)
rec = frappe.db.sql("""select CONCAT(ifnull(c.first_name,''), ' ', ifnull(c.last_name,'')),
c.mobile_no from `tabContact` c, `tabDynamic Link` dl where ifnull(c.mobile_no,'')!='' and
c.docstatus != 2 and dl.parent = c.name%s""" % where_clause)
elif self.send_to == 'All Lead (Open)':
rec = frappe.db.sql("""select lead_name, mobile_no from `tabLead` where
@@ -50,7 +55,6 @@ class SMSCenter(Document):
where ifnull(tabEmployee.cell_number,'')!=''""")
rec_list = ''
for d in rec:
rec_list += d[0] + ' - ' + d[1] + '\n'
self.receiver_list = rec_list

View File

@@ -5,6 +5,7 @@ from __future__ import unicode_literals
import frappe
from frappe import msgprint, _
from frappe.utils import flt
from erpnext import get_company_currency
def execute(filters=None):
if not filters: filters = {}
@@ -14,12 +15,14 @@ def execute(filters=None):
item_details = get_item_details()
data = []
company_currency = get_company_currency(filters["company"])
for d in entries:
if d.stock_qty > 0 or filters.get('show_return_entries', 0):
data.append([
d.name, d.customer, d.territory, d.posting_date, d.item_code,
d.name, d.customer, d.territory, d.warehouse, d.posting_date, d.item_code,
item_details.get(d.item_code, {}).get("item_group"), item_details.get(d.item_code, {}).get("brand"),
d.stock_qty, d.base_net_amount, d.sales_person, d.allocated_percentage, d.contribution_amt
d.stock_qty, d.base_net_amount, d.sales_person, d.allocated_percentage, d.contribution_amt, company_currency
])
if data:
@@ -32,12 +35,105 @@ def get_columns(filters):
if not filters.get("doc_type"):
msgprint(_("Please select the document type first"), raise_exception=1)
return [filters["doc_type"] + ":Link/" + filters["doc_type"] + ":140",
_("Customer") + ":Link/Customer:140", _("Territory") + ":Link/Territory:100", _("Posting Date") + ":Date:100",
_("Item Code") + ":Link/Item:120", _("Item Group") + ":Link/Item Group:120",
_("Brand") + ":Link/Brand:120", _("Qty") + ":Float:100", _("Amount") + ":Currency:120",
_("Sales Person") + ":Link/Sales Person:140", _("Contribution %") + "::110",
_("Contribution Amount") + ":Currency:140"]
columns = [
{
"label": _(filters["doc_type"]),
"options": filters["doc_type"],
"fieldname": frappe.scrub(filters['doc_type']),
"fieldtype": "Link",
"width": 140
},
{
"label": _("Customer"),
"options": "Customer",
"fieldname": "customer",
"fieldtype": "Link",
"width": 140
},
{
"label": _("Territory"),
"options": "Territory",
"fieldname": "territory",
"fieldtype": "Link",
"width": 140
},
{
"label": _("Warehouse"),
"options": "Warehouse",
"fieldname": "warehouse",
"fieldtype": "Link",
"width": 140
},
{
"label": _("Posting Date"),
"fieldname": "posting_date",
"fieldtype": "Date",
"width": 140
},
{
"label": _("Item Code"),
"options": "Item",
"fieldname": "item_code",
"fieldtype": "Link",
"width": 140
},
{
"label": _("Item Group"),
"options": "Item Group",
"fieldname": "item_group",
"fieldtype": "Link",
"width": 140
},
{
"label": _("Brand"),
"options": "Brand",
"fieldname": "brand",
"fieldtype": "Link",
"width": 140
},
{
"label": _("Qty"),
"fieldname": "qty",
"fieldtype": "Float",
"width": 140
},
{
"label": _("Amount"),
"options": "currency",
"fieldname": "amount",
"fieldtype": "Currency",
"width": 140
},
{
"label": _("Sales Person"),
"options": "Sales Person",
"fieldname": "sales_person",
"fieldtype": "Link",
"width": 140
},
{
"label": _("Contribution %"),
"fieldname": "contribution",
"fieldtype": "Float",
"width": 140
},
{
"label": _("Contribution Amount"),
"options": "currency",
"fieldname": "contribution_amt",
"fieldtype": "Currency",
"width": 140
},
{
"label":_("Currency"),
"options": "Currency",
"fieldname":"currency",
"fieldtype":"Link",
"hidden" : 1
}
]
return columns
def get_entries(filters):
date_field = filters["doc_type"] == "Sales Order" and "transaction_date" or "posting_date"
@@ -48,10 +144,10 @@ def get_entries(filters):
conditions, values = get_conditions(filters, date_field)
entries = frappe.db.sql("""
select
SELECT
dt.name, dt.customer, dt.territory, dt.%s as posting_date, dt_item.item_code,
st.sales_person, st.allocated_percentage,
CASE
st.sales_person, st.allocated_percentage, dt_item.warehouse,
CASE
WHEN dt.status = "Closed" THEN dt_item.%s * dt_item.conversion_factor
ELSE dt_item.stock_qty
END as stock_qty,
@@ -63,9 +159,9 @@ def get_entries(filters):
WHEN dt.status = "Closed" THEN ((dt_item.base_net_rate * dt_item.%s * dt_item.conversion_factor) * st.allocated_percentage/100)
ELSE dt_item.base_net_amount * st.allocated_percentage/100
END as contribution_amt
from
FROM
`tab%s` dt, `tab%s Item` dt_item, `tabSales Team` st
where
WHERE
st.parent = dt.name and dt.name = dt_item.parent and st.parenttype = %s
and dt.docstatus = 1 %s order by st.sales_person, dt.name desc
""" %(date_field, qty_field, qty_field, qty_field, filters["doc_type"], filters["doc_type"], '%s', conditions),
@@ -115,7 +211,7 @@ def get_items(filters):
def get_item_details():
item_details = {}
for d in frappe.db.sql("""select name, item_group, brand from `tabItem`""", as_dict=1):
for d in frappe.db.sql("""SELECT `name`, `item_group`, `brand` FROM `tabItem`""", as_dict=1):
item_details.setdefault(d.name, d)
return item_details

View File

@@ -30,7 +30,7 @@ def make_tax_account_and_template(company, account_name, tax_rate, template_name
if accounts:
make_sales_and_purchase_tax_templates(accounts, template_name)
except frappe.NameError:
frappe.message_log.pop()
if frappe.message_log: frappe.message_log.pop()
except RootNotEditable:
pass
@@ -50,7 +50,7 @@ def make_tax_account(company, account_name, tax_rate):
"tax_rate": flt(tax_rate) if tax_rate else None
}).insert(ignore_permissions=True, ignore_mandatory=True)
except frappe.NameError:
frappe.message_log.pop()
if frappe.message_log: frappe.message_log.pop()
abbr = frappe.db.get_value('Company', company, 'abbr')
account = '{0} - {1}'.format(account_name, abbr)
return frappe.get_doc('Account', account)

View File

@@ -95,7 +95,7 @@ def get_exchange_rate(from_currency, to_currency, transaction_date=None):
if not value:
import requests
api_url = "https://frankfurter.erpnext.org/{0}".format(transaction_date)
api_url = "https://frankfurter.app/{0}".format(transaction_date)
response = requests.get(api_url, params={
"base": from_currency,
"symbols": to_currency

View File

@@ -255,13 +255,13 @@ erpnext.stock.delivery_note.set_print_hide = function(doc, cdt, cdn){
var dn_item_fields = frappe.meta.docfield_map['Delivery Note Item'];
var dn_fields_copy = dn_fields;
var dn_item_fields_copy = dn_item_fields;
if (doc.print_without_amount) {
dn_fields['currency'].print_hide = 1;
dn_item_fields['rate'].print_hide = 1;
dn_item_fields['discount_percentage'].print_hide = 1;
dn_item_fields['price_list_rate'].print_hide = 1;
dn_item_fields['amount'].print_hide = 1;
dn_item_fields['discount_amount'].print_hide = 1;
dn_fields['taxes'].print_hide = 1;
} else {
if (dn_fields_copy['currency'].print_hide != 1)
@@ -270,6 +270,8 @@ erpnext.stock.delivery_note.set_print_hide = function(doc, cdt, cdn){
dn_item_fields['rate'].print_hide = 0;
if (dn_item_fields_copy['amount'].print_hide != 1)
dn_item_fields['amount'].print_hide = 0;
if (dn_item_fields_copy['discount_amount'].print_hide != 1)
dn_item_fields['discount_amount'].print_hide = 0;
if (dn_fields_copy['taxes'].print_hide != 1)
dn_fields['taxes'].print_hide = 0;
}

View File

@@ -75,7 +75,7 @@ class DeliveryNote(SellingController):
item_meta = frappe.get_meta("Delivery Note Item")
print_hide_fields = {
"parent": ["grand_total", "rounded_total", "in_words", "currency", "total", "taxes"],
"items": ["rate", "amount", "price_list_rate", "discount_percentage"]
"items": ["rate", "amount", "discount_amount", "price_list_rate", "discount_percentage"]
}
for key, fieldname in print_hide_fields.items():

View File

@@ -1,6 +1,6 @@
frappe.listview_settings['Delivery Note'] = {
add_fields: ["customer", "customer_name", "base_grand_total", "per_installed", "per_billed",
"transporter_name", "grand_total", "is_return", "status"],
add_fields: ["customer", "customer_name", "base_grand_total", "per_installed", "per_billed",
"transporter_name", "grand_total", "is_return", "status", "currency"],
get_indicator: function(doc) {
if(cint(doc.is_return)==1) {
return [__("Return"), "darkgrey", "is_return,=,Yes"];

View File

@@ -458,7 +458,7 @@ $.extend(erpnext.item, {
fields: ["attribute_value"],
limit_start: 0,
limit_page_length: 500,
parent: "Item"
parent: "Item Attribute"
}
}).then((r) => {
if(r.message) {
@@ -579,7 +579,7 @@ $.extend(erpnext.item, {
["attribute_value", "like", term + "%"]
],
fields: ["attribute_value"],
parent: "Item"
parent: "Item Attribute"
},
callback: function(r) {
if (r.message) {

View File

@@ -49,8 +49,9 @@ def update_packing_list_item(doc, packing_item_code, qty, main_item_row, descrip
pi.qty = flt(qty)
pi.description = description
if not pi.warehouse:
pi.warehouse = (main_item_row.warehouse
if (doc.get('is_pos') or not item.default_warehouse) else item.default_warehouse)
pi.warehouse = (main_item_row.warehouse if ((doc.get('is_pos')
or not item.default_warehouse) and main_item_row.warehouse) else item.default_warehouse)
if not pi.batch_no:
pi.batch_no = cstr(main_item_row.get("batch_no"))
if not pi.target_warehouse:

View File

@@ -182,7 +182,8 @@ class PurchaseReceipt(BuyingController):
if warehouse_account.get(d.warehouse):
stock_value_diff = frappe.db.get_value("Stock Ledger Entry",
{"voucher_type": "Purchase Receipt", "voucher_no": self.name,
"voucher_detail_no": d.name}, "stock_value_difference")
"voucher_detail_no": d.name, "warehouse": d.warehouse}, "stock_value_difference")
if not stock_value_diff:
continue
gl_entries.append(self.get_gl_dict({

View File

@@ -6,7 +6,8 @@ def get_data():
'non_standard_fieldnames': {
'Purchase Invoice': 'purchase_receipt',
'Landed Cost Voucher': 'receipt_document',
'Subscription': 'reference_document'
'Subscription': 'reference_document',
'Purchase Receipt': 'return_against'
},
'internal_links': {
'Purchase Order': ['items', 'purchase_order'],
@@ -24,7 +25,7 @@ def get_data():
},
{
'label': _('Returns'),
'items': ['Stock Entry']
'items': ['Purchase Receipt']
},
{
'label': _('Subscription'),

View File

@@ -1,6 +1,6 @@
frappe.listview_settings['Purchase Receipt'] = {
add_fields: ["supplier", "supplier_name", "base_grand_total", "is_subcontracted",
"transporter_name", "is_return", "status", "per_billed"],
"transporter_name", "is_return", "status", "per_billed", "currency"],
get_indicator: function(doc) {
if(cint(doc.is_return)==1) {
return [__("Return"), "darkgrey", "is_return,=,Yes"];

View File

@@ -81,9 +81,9 @@ class SerialNo(StockController):
self.purchase_date = purchase_sle.posting_date
self.purchase_time = purchase_sle.posting_time
self.purchase_rate = purchase_sle.incoming_rate
if purchase_sle.voucher_type == "Purchase Receipt":
if purchase_sle.voucher_type in ("Purchase Receipt", "Purchase Invoice"):
self.supplier, self.supplier_name = \
frappe.db.get_value("Purchase Receipt", purchase_sle.voucher_no,
frappe.db.get_value(purchase_sle.voucher_type, purchase_sle.voucher_no,
["supplier", "supplier_name"])
# If sales return entry
@@ -187,13 +187,14 @@ def process_serial_no(sle):
update_serial_nos(sle, item_det)
def validate_serial_no(sle, item_det):
serial_nos = get_serial_nos(sle.serial_no) if sle.serial_no else []
if item_det.has_serial_no==0:
if sle.serial_no:
if serial_nos:
frappe.throw(_("Item {0} is not setup for Serial Nos. Column must be blank").format(sle.item_code),
SerialNoNotRequiredError)
elif sle.is_cancelled == "No":
if sle.serial_no:
serial_nos = get_serial_nos(sle.serial_no)
if serial_nos:
if cint(sle.actual_qty) != flt(sle.actual_qty):
frappe.throw(_("Serial No {0} quantity {1} cannot be a fraction").format(sle.item_code, sle.actual_qty))
@@ -239,6 +240,12 @@ def validate_serial_no(sle, item_det):
elif sle.actual_qty < 0 or not item_det.serial_no_series:
frappe.throw(_("Serial Nos Required for Serialized Item {0}").format(sle.item_code),
SerialNoRequiredError)
elif serial_nos:
for serial_no in serial_nos:
sr = frappe.db.get_value("Serial No", serial_no, ["name", "warehouse"], as_dict=1)
if sr and sle.actual_qty < 0 and sr.warehouse != sle.warehouse:
frappe.throw(_("Cannot cancel {0} {1} because Serial No {2} does not belong to the warehouse {3}")
.format(sle.voucher_type, sle.voucher_no, serial_no, sle.warehouse))
def has_duplicate_serial_no(sn, sle):
if sn.warehouse:
@@ -246,8 +253,8 @@ def has_duplicate_serial_no(sn, sle):
status = False
if sn.purchase_document_no:
if sle.voucher_type in ['Purchase Receipt', 'Stock Entry'] and \
sn.delivery_document_type not in ['Purchase Receipt', 'Stock Entry']:
if sle.voucher_type in ['Purchase Receipt', 'Stock Entry', "Purchase Invoice"] and \
sn.delivery_document_type not in ['Purchase Receipt', 'Stock Entry', "Purchase Invoice"]:
status = True
if status and sle.voucher_type == 'Stock Entry' and \

View File

@@ -180,7 +180,7 @@ class StockReconciliation(StockController):
frappe.throw(_("Valuation Rate required for Item in row {0}").format(row.idx))
if ((previous_sle and row.qty == previous_sle.get("qty_after_transaction")
and row.valuation_rate == previous_sle.get("valuation_rate"))
and (row.valuation_rate == previous_sle.get("valuation_rate") or row.qty == 0))
or (not previous_sle and not row.qty)):
continue

View File

@@ -13,12 +13,18 @@ def execute(filters=None):
def get_columns():
return [
{
"label": _("Item Name"),
"fieldname": "item_name",
"label": _("Item Code"),
"fieldname": "item_code",
"fieldtype": "Link",
"options": "Item",
"width": 120
},
{
"label": _("Item Name"),
"fieldname": "item_name",
"fieldtype": "Data",
"width": 120
},
{
"label": _("Warehouse"),
"fieldname": "warehouse",
@@ -70,7 +76,7 @@ def get_item_price_qty_data(filters):
if filters.get("item_code"):
conditions += "where a.item_code=%(item_code)s"
item_results = frappe.db.sql("""select a.item_code as item_name, a.name as price_list_name,
item_results = frappe.db.sql("""select a.item_code, a.item_name, a.name as price_list_name,
b.warehouse as warehouse, b.actual_qty as actual_qty
from `tabItem Price` a left join `tabBin` b
ON a.item_code = b.item_code
@@ -86,6 +92,7 @@ def get_item_price_qty_data(filters):
if item_results:
for item_dict in item_results:
data = {
'item_code': item_dict.item_code,
'item_name': item_dict.item_name,
'warehouse': item_dict.warehouse,
'stock_available': item_dict.actual_qty or 0,

View File

@@ -84,6 +84,14 @@ def get_suppliers_details(filters):
is_stock_item=1 and name=pri.item_code)""", as_dict=1):
item_supplier_map.setdefault(d.item_code, []).append(d.supplier)
for d in frappe.db.sql("""select pr.supplier, pri.item_code from
`tabPurchase Invoice` pr, `tabPurchase Invoice Item` pri
where pr.name=pri.parent and pr.docstatus=1 and
ifnull(pr.update_stock, 0) = 1 and pri.item_code=(select name from `tabItem`
where is_stock_item=1 and name=pri.item_code)""", as_dict=1):
if d.item_code not in item_supplier_map:
item_supplier_map.setdefault(d.item_code, []).append(d.supplier)
if supplier:
for item_code, suppliers in item_supplier_map.items():
if supplier not in suppliers:

View File

@@ -176,7 +176,11 @@ class update_entries_after(object):
# rounding as per precision
self.stock_value = flt(self.stock_value, self.precision)
stock_value_difference = self.stock_value - self.prev_stock_value
if self.prev_stock_value < 0 and self.stock_value >= 0 and sle.voucher_type != 'Stock Reconciliation':
stock_value_difference = sle.actual_qty * self.valuation_rate
else:
stock_value_difference = self.stock_value - self.prev_stock_value
self.prev_stock_value = self.stock_value
# update current sle

View File

@@ -2,7 +2,7 @@
{%- if doc.discount_amount -%}
<div class="row">
<div class="col-xs-5 {%- if doc._align_labels_right %} text-right{%- endif -%}">
<label>{{ _("Discount Amount") }}</label></div>
<label>{{ _(doc.meta.get_label('discount_amount')) }}</label></div>
<div class="col-xs-7 text-right">
- {{ doc.get_formatted("discount_amount", doc) }}
</div>