Compare commits

...

96 Commits

Author SHA1 Message Date
Frappe Bot
58dda68430 Merge branch 'hotfix' 2019-02-15 10:22:32 +00:00
Frappe Bot
acf26c8569 bumped to version 11.1.6 2019-02-15 10:22:32 +00:00
Nabin Hait
09a4df74f0 Merge pull request #16645 from nabinhait/tds-fix
fix: Ignore tds account while creating tax withholding category
2019-02-15 14:53:30 +05:30
Nabin Hait
eb0627356b Merge pull request #16650 from nabinhait/general-ledger-fix
fix: show values in account/party currency based in actual entry, no conversion
2019-02-15 14:53:12 +05:30
Nabin Hait
b5c249583a Merge pull request #16651 from netchampfaris/fix-barcode-scanning-ux
fix: Barcode scanning UX
2019-02-15 14:52:42 +05:30
Nabin Hait
b819f104e6 Merge pull request #16653 from nabinhait/item-variants
fix: Enqueued item variants updation if there are more than 30 variants
2019-02-15 14:51:14 +05:30
Nabin Hait
c45962e3ef Merge pull request #16675 from deepeshgarg007/purchase-fix
fix: Purchase order item description fix
2019-02-15 14:50:38 +05:30
Nabin Hait
aa80a223d8 Merge pull request #16674 from deepeshgarg007/address-rep-fix
fix: Address and contact report
2019-02-15 14:26:16 +05:30
Nabin Hait
8788a5c712 Merge pull request #16676 from nabinhait/get-item-details
fix: get item details
2019-02-15 14:24:46 +05:30
Nabin Hait
b1cbe221b7 Merge pull request #16677 from nabinhait/total-qty-patch-fix
fix: Consider parenttype while updating total qty in transactions
2019-02-15 14:24:30 +05:30
Nabin Hait
a0c9c7501b Update update_total_qty_field.py 2019-02-15 14:24:08 +05:30
Nabin Hait
9d85876086 Merge pull request #16679 from nabinhait/get_oustanding
Get outstanding invoices
2019-02-15 14:23:07 +05:30
Sagar Vora
379e6a4635 Merge branch 'hotfix' into address-rep-fix 2019-02-15 13:08:42 +05:30
Nabin Hait
4df7679c65 fix: Get outstanding invoices 2019-02-15 13:08:04 +05:30
Sagar Vora
ebdd8a9710 Merge branch 'hotfix' into purchase-fix 2019-02-15 13:04:32 +05:30
Sagar Vora
921f468950 Merge branch 'hotfix' into get-item-details 2019-02-15 13:03:04 +05:30
Nabin Hait
6f7a4d94ce fix: Consider parenttype while updating total qty in transactions 2019-02-14 19:34:43 +05:30
Nabin Hait
f66c6874ca Merge pull request #16652 from nabinhait/work-order-fix
fix: Make work order from production plan considering already ordered qty
2019-02-14 18:50:30 +05:30
Nabin Hait
54f8ed1282 Merge branch 'hotfix' into item-variants 2019-02-14 18:50:11 +05:30
Nabin Hait
c3698e458f Merge pull request #16666 from nabinhait/deferred-revenue-fix
fix: errors in deferred revenue booking
2019-02-14 18:49:01 +05:30
Nabin Hait
1c6a1dd5c0 Merge branch 'hotfix' into general-ledger-fix 2019-02-14 18:37:40 +05:30
Nabin Hait
0d1ccc357f fix: get item details 2019-02-14 18:30:10 +05:30
deepeshgarg007
867ca63750 fix: Purchase order item description fix 2019-02-14 18:10:47 +05:30
Deepesh Garg
20008946a3 Merge branch 'hotfix' into address-rep-fix 2019-02-14 17:37:41 +05:30
Deepesh Garg
4902f7b2a0 fix: Show tasks in timesheet with status as Closed (#16660) 2019-02-14 17:32:52 +05:30
deepeshgarg007
34f4f24e21 fix: Address and contact report 2019-02-14 17:26:49 +05:30
Nabin Hait
29fcb14c42 fix: errors in deferred revenue booking 2019-02-13 17:18:12 +05:30
Deepesh Garg
4d1bc0ca85 fix: Add total row in analytics report (#16648) 2019-02-13 16:58:46 +05:30
rohitwaghchaure
a0aaeafae8 Merge pull request #16644 from rohitwaghchaure/fix_work_order_time_log_msg
fix: validation message for work order
2019-02-13 09:49:25 +05:30
Faris Ansari
795102125c Merge branch 'hotfix' into fix-barcode-scanning-ux 2019-02-12 18:31:06 +05:30
Nabin Hait
db527bfb24 fix: Enqueued item variants updation if there are more than 30 variants 2019-02-12 18:30:00 +05:30
Nabin Hait
1a3c27bbea fix: Make work order from production plan considering already ordered qty 2019-02-12 17:38:37 +05:30
Faris Ansari
5631ffca68 fix: Barcode scanning UX 2019-02-12 17:12:48 +05:30
Nabin Hait
6447069e50 fix: show values in account/party currency based in actual entry, no conversion 2019-02-12 16:41:20 +05:30
Sagar Vora
e11f2c0107 Merge branch 'hotfix' 2019-02-12 16:34:29 +05:30
Sagar Vora
6837ae3377 bumped to version 11.1.5 2019-02-12 16:54:29 +05:50
Nabin Hait
fdefbdb23b Merge pull request #16609 from nabinhait/multipel_fixes
Multiple fixes
2019-02-12 13:56:06 +05:30
Nabin Hait
c46d995480 Merge pull request #16628 from Zlash65/fix-noti-patch
fix: Notification Control delete
2019-02-12 13:04:45 +05:30
Nabin Hait
e6abee4bd5 Merge pull request #16643 from Zlash65/field-fix
fix: Fieldtype and Fetch From fixes
2019-02-12 13:04:00 +05:30
Nabin Hait
ca536efe7b Merge pull request #16640 from nabinhait/pur_reg_fix
fix: show project even if PI is directly created
2019-02-12 13:01:18 +05:30
Deepesh Garg
da7c20e474 fix: Validate task dates in project (#16586)
* fix: Validate task dates in project

* fix: Test case fix and validation only if date exists

* fix: Added dates in error messages
2019-02-12 12:55:50 +05:30
Rohit Waghchaure
e0412a177c fix: validation message for work order 2019-02-12 11:47:16 +05:30
Zlash65
fc88029d7d fix: fix item field for clinical procedure template 2019-02-12 11:38:27 +05:30
Zlash65
b614fb1d45 fix: make finance book field as link field and rectify fetch_from 2019-02-12 11:30:58 +05:30
Nabin Hait
afef9c1cc7 fix: Ignore tds account while creating tax withholding category 2019-02-12 11:28:20 +05:30
Zlash65
fd3998cfc9 fix: make branch as link field 2019-02-12 11:27:23 +05:30
Nabin Hait
ab50211e18 fix: show project even if PI is directly created 2019-02-11 18:25:18 +05:30
sahil28297
1a7e438fb2 fix(pstch): allow duplicate entries (#16632) 2019-02-11 15:53:04 +05:30
rohitwaghchaure
d95c8cfac3 Merge pull request #16621 from netchampfaris/fix-warehouse-currency
fix: Set company_currency for Warehouse Tree
2019-02-11 14:58:02 +05:30
Zlash65
a206f06af9 delete notification control's docctype entry 2019-02-11 12:01:01 +05:30
Nabin Hait
bb6438af5a Merge pull request #16537 from nabinhait/stock-balance-fix
fix: Fixed error on stock balance report
2019-02-11 11:00:01 +05:30
Faris Ansari
453964728d fix: Set company_currency for Warehouse Tree 2019-02-09 20:27:42 +05:30
Nabin Hait
17e0513270 fix: message if stock reco is enqueued 2019-02-08 16:56:26 +05:30
Nabin Hait
8d4bb3e327 fix: backflush only if transferred item is present in work order 2019-02-08 16:56:26 +05:30
Nabin Hait
450fe309d6 fix: allow updating title of material request 2019-02-08 16:56:26 +05:30
Nabin Hait
e3b0f4f9f6 fix: removed account type filter on employee advance account 2019-02-08 16:56:26 +05:30
Nabin Hait
27af6b377f fix: defered accounting fixes 2019-02-08 16:56:26 +05:30
Faris Ansari
504f317434 fix: BOM Stock Calculated Report (#16585)
- Cast null values to 0 to avoid mathematic errors
2019-02-07 07:15:38 +05:30
Faris Ansari
8ae5dbcac8 fix: Set barcode in Item row after scanning barcode (#16591) 2019-02-07 07:09:49 +05:30
Himanshu
088886e082 Remove illegal character after break (#16589) 2019-02-07 07:09:20 +05:30
Sagar Vora
76120309e3 Merge branch 'hotfix' 2019-02-05 18:40:38 +05:30
Sagar Vora
8aa34a0ce0 bumped to version 11.1.4 2019-02-05 19:00:38 +05:50
Prateeksha Singh
34df5d27a1 Merge pull request #16518 from karthikeyan5/staging-marketplace-features
fix(marketplace): bug in filtering menu_items
2019-02-05 18:09:57 +05:30
karthikeyan5
4cb0a250a0 fix(marketplace): bug in filtering menu_items
> UX improvment for incomplete feature
2019-02-05 18:07:48 +05:30
Nabin Hait
efff826e15 Merge pull request #16556 from nabinhait/payroll-cost-center
fix: Don't force fetch cost center from company in payroll entry
2019-02-05 13:32:16 +05:30
Nabin Hait
8a46df5c4b Removed duplicate fields 2019-02-05 13:31:32 +05:30
Nabin Hait
38b05a1296 fix: Set default cost center in payroll entry 2019-02-05 10:46:41 +05:30
Nabin Hait
294319e71b fix: Don't force fetch cost center from company in payroll entry 2019-02-05 10:37:41 +05:30
Nabin Hait
ad69e29334 Merge pull request #16548 from nabinhait/stock-balance-item
fix: Fetch data based on item group filter in item dashboard stock balance report
2019-02-05 10:36:47 +05:30
Nabin Hait
1c288ca4ab Merge pull request #16558 from deepeshgarg007/production_plan
fix: Validation while getting raw materials for production in Production Plan
2019-02-05 10:35:16 +05:30
Nabin Hait
fe6f1ad244 Update production_plan.py 2019-02-05 10:34:58 +05:30
Nabin Hait
d4e029665c Merge pull request #16569 from nabinhait/salary-allow-on-submit
fix: Allow-on-submit enabled for formula and condition in salary structure
2019-02-05 10:31:24 +05:30
Nabin Hait
b6d2c7eb80 Merge pull request #16570 from saurabh6790/jinja_injection_fix
fix: access request parameter directly
2019-02-05 10:31:08 +05:30
Nabin Hait
7b93e738ad Merge pull request #16576 from nabinhait/pay_reco_fix
fix: Optimising payment reconciliation queries
2019-02-05 10:28:03 +05:30
Nabin Hait
025e780f31 Merge pull request #16575 from rohitwaghchaure/fixed_job_card_not_working
fix: job card not working if transfer against work order
2019-02-05 10:27:12 +05:30
Nabin Hait
56bff95e15 Merge pull request #16571 from Thunderbottom/purchase-invoice-fix
fix(purchase_invoice): fix undefined variable
2019-02-05 10:26:41 +05:30
Nabin Hait
ac18498ca5 fix: Optimising payment reconciliation queries 2019-02-04 21:13:43 +05:30
Rohit Waghchaure
780c6b0d77 fix: job card not working if transfer against work order 2019-02-04 21:04:48 +05:30
Chinmay Pai
125505f2aa fix(purchase_invoice): fix undefined variable
fixes issue while creating purchase invoice

Signed-off-by: Chinmay Pai <chinmaydpai@gmail.com>
2019-02-04 16:30:20 +05:30
Saurabh
bbebceb31a fix: access request parameter directly 2019-02-04 15:56:23 +05:30
Nabin Hait
ff05ee50e0 fix: Allow-on-submit enabled for formula and condition in salary structure 2019-02-04 14:42:57 +05:30
Deepesh Garg
d442d06947 Update production_plan.py 2019-02-03 12:45:20 +05:30
dgarg007
f667cff5a6 fix: Validation while getting raw materils for production in Production Plan 2019-02-02 21:57:00 +05:30
rohitwaghchaure
752f2f1805 Merge pull request #16547 from rohitwaghchaure/project_status_email_fix
fix: check open status projects for project status update
2019-02-02 13:06:29 +05:30
Saurabh
aba611e09f Merge branch 'hotfix' into project_status_email_fix 2019-02-01 15:01:26 +05:30
Nabin Hait
e1c75a9d55 fix: fixed salary structure assignment patch (#16546)
* fix: fixed salary structure assignment patch

* fix: patch
2019-02-01 12:25:40 +05:30
Nabin Hait
f3f4ce9b87 fix: Fetch data based on item group filter in item dashboard stock balance report 2019-02-01 12:01:19 +05:30
Rohit Waghchaure
a4645b6d17 fix: check open status projects for project status update 2019-02-01 11:37:22 +05:30
Sagar Vora
ec5faaeae6 Merge branch 'hotfix' into stock-balance-fix 2019-01-31 18:46:06 +05:30
Nabin Hait
9ea19b8fe1 fix: Fixed error on stock balance report 2019-01-31 15:53:25 +05:30
Sagar Vora
7a2163ca39 Merge branch 'hotfix' 2019-01-31 13:33:07 +05:30
Sagar Vora
fea55fc018 bumped to version 11.1.3 2019-01-31 13:53:07 +05:50
Nabin Hait
a85f008f30 Merge pull request #16528 from adityahase/payment-request-usability
fix(accounts): fetch subscription details only if required fields are populated
2019-01-31 10:27:27 +05:30
Sagar Vora
7ea2497b9a Fix salary patch (#16531)
fix: salary structure assignment patch, add .vscode to gitignore
2019-01-31 09:17:29 +05:30
Sagar Vora
76728b87ab fix: value missing for selling settings - sales_update_frequency (#16530) 2019-01-31 08:19:38 +05:30
Aditya Hase
66833f109b fix(accounts): fetch subscription details only if required fields are populated 2019-01-30 19:40:40 +05:30
51 changed files with 297 additions and 283 deletions

1
.gitignore vendored
View File

@@ -12,4 +12,5 @@ erpnext/docs/current
*.swo
__pycache__
*~
.vscode/
node_modules/

View File

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

View File

@@ -60,7 +60,7 @@ def get_booking_dates(doc, item, start_date=None, end_date=None):
deferred_account = "deferred_revenue_account" if doc.doctype=="Sales Invoice" else "deferred_expense_account"
last_gl_entry, skip = False, False
booking_end_date = getdate(add_days(today(), -1)) if not end_date else end_date
booking_end_date = getdate(add_days(today(), -1) if not end_date else end_date)
if booking_end_date < item.service_start_date or \
(item.service_stop_date and booking_end_date.month > item.service_stop_date.month):
return None, None, None, True
@@ -71,7 +71,7 @@ def get_booking_dates(doc, item, start_date=None, end_date=None):
last_gl_entry = True
booking_end_date = item.service_stop_date
booking_start_date = getdate(add_months(today(), -1)) if not start_date else start_date
booking_start_date = getdate(add_months(today(), -1) if not start_date else start_date)
booking_start_date = booking_start_date \
if booking_start_date > item.service_start_date else item.service_start_date
@@ -113,7 +113,6 @@ def calculate_amount_and_base_amount(doc, item, last_gl_entry, total_days, total
group by voucher_detail_no
'''.format(total_credit_debit, total_credit_debit_currency),
(doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), as_dict=True)
already_booked_amount = gl_entries_details[0].total_credit if gl_entries_details else 0
base_amount = flt(item.base_net_amount - already_booked_amount, item.precision("base_net_amount"))
if account_currency==doc.company_currency:
@@ -128,15 +127,19 @@ def book_deferred_income_or_expense(doc, start_date=None, end_date=None):
# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
# start_date: 1st of the last month or the start date
# end_date: end_date or today-1
enable_check = "enable_deferred_revenue" \
if doc.doctype=="Sales Invoice" else "enable_deferred_expense"
gl_entries = []
for item in doc.get('items'):
if not item.get(enable_check): continue
skip = False
last_gl_entry, booking_start_date, booking_end_date, skip = \
get_booking_dates(doc, item, start_date, end_date)
if skip: continue
total_days = date_diff(item.service_end_date, item.service_start_date)
total_days = date_diff(item.service_end_date, item.service_start_date) + 1
total_booking_days = date_diff(booking_end_date, booking_start_date) + 1
account_currency = get_account_currency(item.expense_account)
@@ -175,6 +178,10 @@ def book_deferred_income_or_expense(doc, start_date=None, end_date=None):
'project': project
}, account_currency)
)
if gl_entries:
make_gl_entries(gl_entries, cancel=(doc.docstatus == 2), merge_entries=True)
try:
make_gl_entries(gl_entries, cancel=(doc.docstatus == 2), merge_entries=True)
frappe.db.commit()
except:
frappe.db.rollback()
frappe.log_error(message = frappe.get_traceback(), title = _("Error while processing deferred accounting for {0}").format(doc.name))

View File

@@ -171,7 +171,7 @@ class PaymentEntry(AccountsController):
if not frappe.db.exists(self.party_type, self.party):
frappe.throw(_("Invalid {0}: {1}").format(self.party_type, self.party))
if self.party_account:
if self.party_account and self.party_type in ("Customer", "Supplier"):
self.validate_account_type(self.party_account,
[erpnext.get_party_account_type(self.party_type)])
@@ -689,7 +689,7 @@ def get_party_details(company, party_type, party, date, cost_center=None):
account_currency = get_account_currency(party_account)
account_balance = get_balance_on(party_account, date, cost_center=cost_center)
_party_name = "title" if party_type == "Student" else party_type.lower() + "_name"
_party_name = "title" if party_type in ("Student", "Shareholder") else party_type.lower() + "_name"
party_name = frappe.db.get_value(party_type, party, _party_name)
party_balance = get_balance_on(party_type=party_type, party=party, cost_center=cost_center)
if party_type in ["Customer", "Supplier"]:

View File

@@ -54,7 +54,7 @@ frappe.ui.form.on("Payment Request", "is_a_subscription", function(frm) {
frm.toggle_reqd("payment_gateway_account", frm.doc.is_a_subscription);
frm.toggle_reqd("subscription_plans", frm.doc.is_a_subscription);
if (frm.doc.is_a_subscription) {
if (frm.doc.is_a_subscription && frm.doc.reference_doctype && frm.doc.reference_name) {
frappe.call({
method: "erpnext.accounts.doctype.payment_request.payment_request.get_subscription_details",
args: {"reference_doctype": frm.doc.reference_doctype, "reference_name": frm.doc.reference_name},

View File

@@ -231,7 +231,7 @@ class PurchaseInvoice(BuyingController):
item.expense_account = warehouse_account[item.warehouse]["account"]
else:
item.expense_account = stock_not_billed_account
elif item.is_fixed_asset and d.pr_detail:
elif item.is_fixed_asset and item.pr_detail:
item.expense_account = asset_received_but_not_billed
elif not item.expense_account and for_validate:
throw(_("Expense account is mandatory for item {0}").format(item.item_code or item.item_name))

View File

@@ -101,7 +101,7 @@ def set_account_currency(filters):
frappe.db.get_value(filters.party_type, filters.party[0], "default_currency"))
filters["account_currency"] = account_currency or filters.company_currency
if filters.account_currency != filters.company_currency:
if filters.account_currency != filters.company_currency and not filters.presentation_currency:
filters.presentation_currency = filters.account_currency
return filters

View File

@@ -193,7 +193,7 @@ def get_invoice_po_pr_map(invoice_list):
pi_items = frappe.db.sql("""
select parent, purchase_order, purchase_receipt, po_detail, project
from `tabPurchase Invoice Item`
where parent in (%s) and (ifnull(purchase_order, '') != '' or ifnull(purchase_receipt, '') != '')
where parent in (%s)
""" % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
invoice_po_pr_map = {}

View File

@@ -104,7 +104,7 @@ def convert_to_presentation_currency(gl_entries, currency_info):
credit_in_account_currency = flt(entry['credit_in_account_currency'])
account_currency = entry['account_currency']
if account_currency != presentation_currency or (account_currency == presentation_currency and not is_p_or_l_account(account)):
if account_currency != presentation_currency:
value = debit or credit
date = currency_info['report_date'] if not is_p_or_l_account(account) else entry['posting_date']

View File

@@ -615,38 +615,26 @@ def get_held_invoices(party_type, party):
return held_invoices
def get_outstanding_invoices(party_type, party, account, condition=None, limit=1000):
def get_outstanding_invoices(party_type, party, account, condition=None, limit=None):
outstanding_invoices = []
precision = frappe.get_precision("Sales Invoice", "outstanding_amount")
precision = frappe.get_precision("Sales Invoice", "outstanding_amount") or 2
if erpnext.get_party_account_type(party_type) == 'Receivable':
dr_or_cr = "debit_in_account_currency - credit_in_account_currency"
payment_dr_or_cr = "payment_gl_entry.credit_in_account_currency - payment_gl_entry.debit_in_account_currency"
payment_dr_or_cr = "credit_in_account_currency - debit_in_account_currency"
else:
dr_or_cr = "credit_in_account_currency - debit_in_account_currency"
payment_dr_or_cr = "payment_gl_entry.debit_in_account_currency - payment_gl_entry.credit_in_account_currency"
payment_dr_or_cr = "debit_in_account_currency - credit_in_account_currency"
invoice = 'Sales Invoice' if erpnext.get_party_account_type(party_type) == 'Receivable' else 'Purchase Invoice'
held_invoices = get_held_invoices(party_type, party)
limit_cond = "limit %s" % (limit or 1000)
limit_cond = "limit %s" % limit if limit else ""
invoice_list = frappe.db.sql("""
select
voucher_no, voucher_type, posting_date, ifnull(sum({dr_or_cr}), 0) as invoice_amount,
(
select ifnull(sum({payment_dr_or_cr}), 0)
from `tabGL Entry` payment_gl_entry
where payment_gl_entry.against_voucher_type = invoice_gl_entry.voucher_type
and if(invoice_gl_entry.voucher_type='Journal Entry',
payment_gl_entry.against_voucher = invoice_gl_entry.voucher_no,
payment_gl_entry.against_voucher = invoice_gl_entry.against_voucher)
and payment_gl_entry.party_type = invoice_gl_entry.party_type
and payment_gl_entry.party = invoice_gl_entry.party
and payment_gl_entry.account = invoice_gl_entry.account
and {payment_dr_or_cr} > 0
) as payment_amount
voucher_no, voucher_type, posting_date, ifnull(sum({dr_or_cr}), 0) as invoice_amount
from
`tabGL Entry` invoice_gl_entry
`tabGL Entry`
where
party_type = %(party_type)s and party = %(party)s
and account = %(account)s and {dr_or_cr} > 0
@@ -655,11 +643,9 @@ def get_outstanding_invoices(party_type, party, account, condition=None, limit=1
and (against_voucher = '' or against_voucher is null))
or (voucher_type not in ('Journal Entry', 'Payment Entry')))
group by voucher_type, voucher_no
having (invoice_amount - payment_amount) > 0.005
order by posting_date, name {limit_cond}""".format(
dr_or_cr=dr_or_cr,
invoice = invoice,
payment_dr_or_cr=payment_dr_or_cr,
condition=condition or "",
limit_cond = limit_cond
), {
@@ -668,25 +654,46 @@ def get_outstanding_invoices(party_type, party, account, condition=None, limit=1
"account": account,
}, as_dict=True)
for d in invoice_list:
if not d.voucher_type == "Purchase Invoice" or d.voucher_no not in held_invoices:
due_date = frappe.db.get_value(
d.voucher_type, d.voucher_no, "posting_date" if party_type == "Employee" else "due_date")
payment_entries = frappe.db.sql("""
select against_voucher_type, against_voucher,
ifnull(sum({payment_dr_or_cr}), 0) as payment_amount
from `tabGL Entry`
where party_type = %(party_type)s and party = %(party)s
and account = %(account)s
and {payment_dr_or_cr} > 0
and against_voucher is not null and against_voucher != ''
group by against_voucher_type, against_voucher
""".format(payment_dr_or_cr=payment_dr_or_cr), {
"party_type": party_type,
"party": party,
"account": account,
}, as_dict=True)
outstanding_invoices.append(
frappe._dict({
'voucher_no': d.voucher_no,
'voucher_type': d.voucher_type,
'posting_date': d.posting_date,
'invoice_amount': flt(d.invoice_amount),
'payment_amount': flt(d.payment_amount),
'outstanding_amount': flt(d.invoice_amount - d.payment_amount, precision),
'due_date': due_date
})
)
pe_map = frappe._dict()
for d in payment_entries:
pe_map.setdefault((d.against_voucher_type, d.against_voucher), d.payment_amount)
for d in invoice_list:
payment_amount = pe_map.get((d.voucher_type, d.voucher_no), 0)
outstanding_amount = flt(d.invoice_amount - payment_amount, precision)
if outstanding_amount > 0.5 / (10**precision):
if not d.voucher_type == "Purchase Invoice" or d.voucher_no not in held_invoices:
due_date = frappe.db.get_value(
d.voucher_type, d.voucher_no, "posting_date" if party_type == "Employee" else "due_date")
outstanding_invoices.append(
frappe._dict({
'voucher_no': d.voucher_no,
'voucher_type': d.voucher_type,
'posting_date': d.posting_date,
'invoice_amount': flt(d.invoice_amount),
'payment_amount': payment_amount,
'outstanding_amount': outstanding_amount,
'due_date': due_date
})
)
outstanding_invoices = sorted(outstanding_invoices, key=lambda k: k['due_date'] or getdate(nowdate()))
return outstanding_invoices
@@ -859,5 +866,3 @@ def get_allow_cost_center_in_entry_of_bs_account():
def generator():
return cint(frappe.db.get_value('Accounts Settings', None, 'allow_cost_center_in_entry_of_bs_account'))
return frappe.local_cache("get_allow_cost_center_in_entry_of_bs_account", (), generator, regenerate_if_none=True)

View File

@@ -1812,8 +1812,9 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "company.default_finance_book",
"fieldname": "default_finance_book",
"fieldtype": "Read Only",
"fieldtype": "Link",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -1824,12 +1825,12 @@
"label": "Default Finance Book",
"length": 0,
"no_copy": 0,
"options": "company.default_finance_book",
"options": "Finance Book",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
@@ -1882,7 +1883,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2019-01-15 16:12:48.314196",
"modified": "2019-02-12 11:29:01.747819",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset",

View File

@@ -456,7 +456,7 @@ def make_rm_stock_entry(purchase_order, rm_items):
items_dict = {
rm_item_code: {
"item_name": rm_item_data["item_name"],
"description": item_wh[rm_item_code].get('description'),
"description": item_wh.get(rm_item_code, {}).get('description', ""),
'qty': rm_item_data["qty"],
'from_warehouse': rm_item_data["warehouse"],
'stock_uom': rm_item_data["stock_uom"],

View File

@@ -1,12 +1,13 @@
{
"add_total_row": 0,
"add_total_row": 1,
"creation": "2018-10-05 16:08:24.156448",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2018-10-05 16:08:33.272201",
"modified": "2019-02-12 14:32:29.107109",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Analytics",

View File

@@ -28,7 +28,7 @@ class WoocommerceSettings(Document):
if not frappe.get_value("Custom Field",{"name":i[0]}) or not frappe.get_value("Custom Field",{"name":i[1]}):
create_custom_field_id_and_check_status = True
break;
break
if create_custom_field_id_and_check_status:

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 1,
@@ -55,7 +56,7 @@
"collapsible": 0,
"columns": 0,
"fieldname": "item_code",
"fieldtype": "Read Only",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -71,7 +72,7 @@
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
@@ -707,7 +708,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-08-08 13:00:06.260997",
"modified": "2019-02-12 11:37:18.713344",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Clinical Procedure Template",

View File

@@ -19,7 +19,6 @@ frappe.ui.form.on('Employee Advance', {
filters: {
"root_type": "Asset",
"is_group": 0,
"account_type": "Payable",
"company": frm.doc.company
}
};

View File

@@ -95,6 +95,8 @@ frappe.ui.form.on('Payroll Entry', {
},
setup: function (frm) {
frm.add_fetch('company', 'cost_center', 'cost_center');
frm.set_query("payment_account", function () {
var account_types = ["Bank", "Cash"];
return {

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 1,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
@@ -861,7 +862,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "company.cost_center",
"default": ":Company",
"fetch_from": "",
"fieldname": "cost_center",
"fieldtype": "Link",
"hidden": 0,
@@ -1189,7 +1191,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-08-21 16:15:45.276711",
"modified": "2019-02-05 10:41:08.865842",
"modified_by": "Administrator",
"module": "HR",
"name": "Payroll Entry",

View File

@@ -21,6 +21,8 @@ class TestPayrollEntry(unittest.TestCase):
make_earning_salary_component(setup=True)
make_deduction_salary_component(setup=True)
frappe.db.set_value("HR Settings", None, "email_salary_slip_to_employee", 0)
def test_payroll_entry(self): # pylint: disable=no-self-use
company = erpnext.get_default_company()
for data in frappe.get_all('Salary Component', fields = ["name"]):

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
@@ -348,7 +349,7 @@
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
@@ -417,7 +418,7 @@
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
@@ -692,7 +693,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-09-20 16:59:33.622652",
"modified": "2019-02-04 14:41:56.030991",
"modified_by": "Administrator",
"module": "HR",
"name": "Salary Detail",

View File

@@ -195,7 +195,7 @@
"columns": 0,
"fetch_from": "employee.branch",
"fieldname": "branch",
"fieldtype": "Read Only",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -208,11 +208,11 @@
"no_copy": 0,
"oldfieldname": "branch",
"oldfieldtype": "Link",
"options": "",
"options": "Branch",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
@@ -1906,7 +1906,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2019-01-30 11:28:11.774739",
"modified": "2019-02-12 11:24:20.848207",
"modified_by": "Administrator",
"module": "HR",
"name": "Salary Slip",

View File

@@ -20,7 +20,7 @@ class SalaryStructureAssignment(Document):
if self.from_date:
if frappe.db.exists("Salary Structure Assignment", {"employee": self.employee, "from_date": self.from_date, "docstatus": 1}):
frappe.throw("Salary Structure Assignment for Employee already exists")
frappe.throw(_("Salary Structure Assignment for Employee already exists"), DuplicateAssignment)
if joining_date and getdate(self.from_date) < joining_date:
frappe.throw(_("From Date {0} cannot be before employee's joining Date {1}")

View File

@@ -78,39 +78,6 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "operation",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Item operation",
"length": 0,
"no_copy": 0,
"options": "Operation",
"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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@@ -926,38 +893,6 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "allow_alternative_item",
"fieldtype": "Check",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Allow Alternative Item",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"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,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@@ -1115,4 +1050,4 @@
"track_changes": 0,
"track_seen": 0,
"track_views": 0
}
}

View File

@@ -57,7 +57,7 @@ class JobCard(Document):
.format(d.idx, d.item_code))
if self.get('operation') == d.operation:
child = self.append('items', {
self.append('items', {
'item_code': d.item_code,
'source_warehouse': d.source_warehouse,
'uom': frappe.db.get_value("Item", d.item_code, 'stock_uom'),
@@ -108,6 +108,10 @@ class JobCard(Document):
if not self.items:
self.transferred_qty = self.for_quantity if self.docstatus == 1 else 0
doc = frappe.get_doc('Work Order', self.get('work_order'))
if doc.transfer_material_against == 'Work Order' or doc.skip_transfer:
return
if self.items:
self.transferred_qty = frappe.db.get_value('Stock Entry', {
'job_card': self.name,

View File

@@ -276,8 +276,8 @@ class ProductionPlan(Document):
item_dict[(d.item_code, d.material_request_item, d.warehouse)] = item_details
else:
item_details.update({
"qty":flt(item_dict.get((d.item_code, d.sales_order, d.warehouse),{})
.get("qty")) + flt(d.planned_qty)
"qty": flt(item_dict.get((d.item_code, d.sales_order, d.warehouse),{})
.get("qty")) + (flt(d.planned_qty) - flt(d.ordered_qty))
})
item_dict[(d.item_code, d.sales_order, d.warehouse)] = item_details
@@ -567,7 +567,7 @@ def get_items_for_material_requests(doc, sales_order=None, company=None):
else:
item_details = get_subitems(doc, data, item_details, bom_no, company,
include_non_stock_items, include_subcontracted_items, 1, planned_qty=planned_qty)
else:
elif data.get('item_code'):
item_master = frappe.get_doc('Item', data['item_code']).as_dict()
purchase_uom = item_master.purchase_uom or item_master.stock_uom
conversion_factor = 0

View File

@@ -13,16 +13,16 @@ def execute(filters=None):
data = get_bom_stock(filters)
qty_to_make = filters.get("qty_to_make")
for rows in data:
item_map = get_item_details(rows[0])
reqd_qty = qty_to_make * rows[3]
last_pur_price = frappe.db.get_value("Item", rows[0], "last_purchase_rate")
if rows[4] > 0:
diff_qty = rows[4] - reqd_qty
summ_data.append([rows[0], rows[1], item_map[rows[0]]["manufacturer"], item_map[rows[0]]["manufacturer_part_no"], rows[3], rows[4], reqd_qty, diff_qty, last_pur_price])
for row in data:
item_map = get_item_details(row.item_code)
reqd_qty = qty_to_make * row.actual_qty
last_pur_price = frappe.db.get_value("Item", row.item_code, "last_purchase_rate")
if row.to_build > 0:
diff_qty = row.to_build - reqd_qty
summ_data.append([row.item_code, row.description, item_map[row.item_code]["manufacturer"], item_map[row.item_code]["manufacturer_part_no"], row.actual_qty, row.to_build, reqd_qty, diff_qty, last_pur_price])
else:
diff_qty = 0 - reqd_qty
summ_data.append([rows[0], rows[1], item_map[rows[0]]["manufacturer"], item_map[rows[0]]["manufacturer_part_no"], rows[3], "0.000", reqd_qty, diff_qty, last_pur_price])
summ_data.append([row.item_code, row.description, item_map[row.item_code]["manufacturer"], item_map[row.item_code]["manufacturer_part_no"], row.actual_qty, "0.000", reqd_qty, diff_qty, last_pur_price])
return columns, summ_data
@@ -72,8 +72,8 @@ def get_bom_stock(filters):
bom_item.item_code,
bom_item.description,
bom_item.{qty_field},
sum(ledger.actual_qty) as actual_qty,
sum(FLOOR(ledger.actual_qty / bom_item.{qty_field}))as to_build
ifnull(sum(ledger.actual_qty), 0) as actual_qty,
ifnull(sum(FLOOR(ledger.actual_qty / bom_item.{qty_field})), 0) as to_build
FROM
{table} AS bom_item
LEFT JOIN `tabBin` AS ledger
@@ -83,7 +83,7 @@ def get_bom_stock(filters):
WHERE
bom_item.parent = '{bom}' and bom_item.parenttype='BOM'
GROUP BY bom_item.item_code""".format(qty_field=qty_field, table=table, conditions=conditions, bom=bom))
GROUP BY bom_item.item_code""".format(qty_field=qty_field, table=table, conditions=conditions, bom=bom), as_dict=1)
def get_item_details(item_code):
items = frappe.db.sql("""select it.item_group, it.item_name, it.stock_uom, it.name, it.brand, it.description, it.manufacturer_part_no, it.manufacturer from tabItem it where it.item_code = %s""", item_code, as_dict=1)

View File

@@ -1,13 +1,14 @@
{
"add_total_row": 0,
"add_total_row": 1,
"creation": "2018-10-11 19:28:37.085066",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"letter_head": "",
"modified": "2018-10-11 19:28:37.085066",
"modified": "2019-02-12 14:32:16.392521",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Production Analytics",

View File

@@ -585,3 +585,4 @@ erpnext.patches.v11_0.rename_additional_salary_component_additional_salary
erpnext.patches.v11_0.renamed_from_to_fields_in_project
erpnext.patches.v11_0.add_permissions_in_gst_settings
erpnext.patches.v11_1.setup_guardian_role
execute:frappe.delete_doc('DocType', 'Notification Control')

View File

@@ -27,8 +27,10 @@ def execute():
for company in companies:
copy_doc = frappe.copy_doc(department_doc)
copy_doc.update({"company": company.name})
copy_doc.insert()
try:
copy_doc.insert()
except frappe.DuplicateEntryError:
pass
# append list of new department for each company
comp_dict[company.name][department.name] = copy_doc.name

View File

@@ -4,6 +4,7 @@
from __future__ import unicode_literals
import frappe
from datetime import datetime
from frappe.utils import getdate
from erpnext.hr.doctype.salary_structure_assignment.salary_structure_assignment import DuplicateAssignment
def execute():
@@ -31,14 +32,22 @@ def execute():
where is_active='Yes'
AND employee in (select name from `tabEmployee` where ifNull(status, '') != 'Left')
""".format(cols), as_dict=1)
for d in ss_details:
try:
joining_date, relieving_date = frappe.db.get_value("Employee", d.employee,
["date_of_joining", "relieving_date"])
from_date = d.from_date
if joining_date and getdate(from_date) < joining_date:
from_date = joining_date
elif relieving_date and getdate(from_date) > relieving_date:
continue
s = frappe.new_doc("Salary Structure Assignment")
s.employee = d.employee
s.employee_name = d.employee_name
s.salary_structure = d.salary_structure
s.from_date = d.from_date
s.from_date = from_date
s.to_date = d.to_date if isinstance(d.to_date, datetime) else None
s.base = d.get("base")
s.variable = d.get("variable")

View File

@@ -19,9 +19,10 @@ def execute():
SELECT
parent, SUM(qty) as qty
FROM
`tab%s Item`
`tab{0} Item`
where parenttype = '{0}'
GROUP BY parent
''' % (doctype), as_dict = True)
'''.format(doctype), as_dict = True)
# Query to update total_qty might become too big, Update in batches
# batch_size is chosen arbitrarily, Don't try too hard to reason about it

View File

@@ -66,11 +66,11 @@ class Project(Document):
def validate(self):
self.validate_project_name()
self.validate_dates()
self.validate_weights()
self.sync_tasks()
self.tasks = []
self.load_tasks()
self.validate_dates()
self.send_welcome_email()
self.update_percent_complete()
@@ -79,6 +79,24 @@ class Project(Document):
frappe.throw(_("Project {0} already exists").format(frappe.safe_decode(self.project_name)))
def validate_dates(self):
if self.tasks:
for d in self.tasks:
if self.expected_start_date:
if d.start_date and getdate(d.start_date) < getdate(self.expected_start_date):
frappe.throw(_("Start date of task <b>{0}</b> cannot be less than <b>{1}</b> expected start date <b>{2}</b>")
.format(d.title, self.name, self.expected_start_date))
if d.end_date and getdate(d.end_date) < getdate(self.expected_start_date):
frappe.throw(_("End date of task <b>{0}</b> cannot be less than <b>{1}</b> expected start date <b>{2}</b>")
.format(d.title, self.name, self.expected_start_date))
if self.expected_end_date:
if d.start_date and getdate(d.start_date) > getdate(self.expected_end_date):
frappe.throw(_("Start date of task <b>{0}</b> cannot be greater than <b>{1}</b> expected end date <b>{2}</b>")
.format(d.title, self.name, self.expected_end_date))
if d.end_date and getdate(d.end_date) > getdate(self.expected_end_date):
frappe.throw(_("End date of task <b>{0}</b> cannot be greater than <b>{1}</b> expected end date <b>{2}</b>")
.format(d.title, self.name, self.expected_end_date))
if self.expected_start_date and self.expected_end_date:
if getdate(self.expected_end_date) < getdate(self.expected_start_date):
frappe.throw(_("Expected End Date can not be less than Expected Start Date"))
@@ -459,7 +477,7 @@ def get_projects_for_collect_progress(frequency, fields):
fields.extend(["name"])
return frappe.get_all("Project", fields = fields,
filters = {'collect_progress': 1, 'frequency': frequency})
filters = {'collect_progress': 1, 'frequency': frequency, 'status': 'Open'})
def send_project_update_email_to_users(project):
doc = frappe.get_doc('Project', project)

View File

@@ -44,12 +44,6 @@ class Task(NestedSet):
if self.act_start_date and self.act_end_date and getdate(self.act_start_date) > getdate(self.act_end_date):
frappe.throw(_("'Actual Start Date' can not be greater than 'Actual End Date'"))
if(self.project):
if frappe.db.exists("Project", self.project):
expected_end_date = frappe.db.get_value("Project", self.project, "expected_end_date")
if self.exp_end_date and expected_end_date and getdate(self.exp_end_date) > getdate(expected_end_date) :
frappe.throw(_("Expected end date cannot be after Project: <b>'{0}'</b> Expected end date").format(self.project), EndDateCannotBeGreaterThanProjectEndDateError)
def validate_status(self):
if self.status!=self.get_db_value("status") and self.status == "Closed":
for d in self.depends_on:

View File

@@ -5,7 +5,7 @@ import frappe
import unittest
from frappe.utils import getdate, nowdate, add_days
from erpnext.projects.doctype.task.task import CircularReferenceError, EndDateCannotBeGreaterThanProjectEndDateError
from erpnext.projects.doctype.task.task import CircularReferenceError
class TestTask(unittest.TestCase):
def test_circular_reference(self):
@@ -97,15 +97,6 @@ class TestTask(unittest.TestCase):
self.assertEqual(frappe.db.get_value("Task", task.name, "status"), "Overdue")
def test_end_date_validation(self):
task_end = create_task("Testing_Enddate_validation", add_days(nowdate(), 35), add_days(nowdate(), 45), save=False)
pro = frappe.get_doc("Project", task_end.project)
pro.expected_end_date = add_days(nowdate(), 40)
pro.save()
self.assertRaises(EndDateCannotBeGreaterThanProjectEndDateError, task_end.save)
def create_task(subject, start=None, end=None, depends_on=None, project=None, save=True):
if not frappe.db.exists("Task", subject):
task = frappe.new_doc('Task')

View File

@@ -18,7 +18,7 @@ frappe.ui.form.on("Timesheet", {
return{
filters: {
'project': child.project,
'status': ["!=", "Closed"]
'status': ["!=", "Cancelled"]
}
}
}

View File

@@ -276,13 +276,11 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
scan_barcode: function() {
let scan_barcode_field = this.frm.fields_dict["scan_barcode"];
let show_description = function(idx, item_code, exist=null) {
if(exist) {
scan_barcode_field.set_new_description(__('Row : ') + idx + ' ' +
item_code + __(' Qty increased by 1'));
let show_description = function(idx, exist = null) {
if (exist) {
scan_barcode_field.set_new_description(__('Row #{0}: Qty increased by 1', [idx]));
} else {
scan_barcode_field.set_new_description(__('New row : ') + idx + ' ' +
item_code + __(' Created'));
scan_barcode_field.set_new_description(__('Row #{0}: Item added', [idx]));
}
}
@@ -291,38 +289,39 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
method: "erpnext.selling.page.point_of_sale.point_of_sale.search_serial_or_batch_or_barcode_number",
args: { search_value: this.frm.doc.scan_barcode }
}).then(r => {
if(r && r.message && r.message.item_code) {
let child = "";
let add_row_index = -1;
let cur_grid= this.frm.fields_dict["items"].grid;
this.frm.doc.items.map(d => {
if(d.item_code==r.message.item_code){
add_row_index = d.idx;
return;
} else if(!d.item_code && add_row_index==-1) {
add_row_index = d.idx;
}
});
if(add_row_index == -1) {
child = frappe.model.add_child(this.frm.doc, cur_grid.doctype, "items", add_row_index);
} else {
child = cur_grid.get_grid_row(add_row_index-1).doc;
}
show_description(child.idx, r.message.item_code, child.item_code);
frappe.model.set_value(child.doctype, child.name, {
"item_code": r.message.item_code,
"qty": (child.qty || 0) + 1
});
const data = r && r.message;
if (!data) {
scan_barcode_field.set_new_description(__('Cannot find Item with this barcode'));
return;
}
else{
scan_barcode_field.set_new_description(this.frm.doc.scan_barcode +__(' does not exist!'));
let cur_grid = this.frm.fields_dict.items.grid;
let row_to_modify = null;
const existing_item_row = this.frm.doc.items.find(d => d.item_code === data.item_code);
const blank_item_row = this.frm.doc.items.find(d => !d.item_code);
if (existing_item_row) {
row_to_modify = existing_item_row;
} else if (blank_item_row) {
row_to_modify = blank_item_row;
}
if (!row_to_modify) {
// add new row
row_to_modify = frappe.model.add_child(this.frm.doc, cur_grid.doctype, 'items');
}
show_description(row_to_modify.idx, row_to_modify.item_code);
frappe.model.set_value(row_to_modify.doctype, row_to_modify.name, {
item_code: data.item_code,
qty: (row_to_modify.qty || 0) + 1
});
this.frm.refresh_field('items');
});
scan_barcode_field.set_value("");
scan_barcode_field.set_value('');
}
return false;
},

View File

@@ -53,7 +53,20 @@ export default {
image: null,
sections: [],
menu_items: [
};
},
computed: {
is_own_item() {
let is_own_item = false;
if(this.item) {
if(this.item.hub_seller === hub.settings.hub_seller_name) {
is_own_item = true;
}
}
return is_own_item;
},
menu_items(){
return [
{
label: __('Save Item'),
condition: hub.is_user_registered() && !this.is_own_item,
@@ -75,17 +88,6 @@ export default {
action: this.unpublish_item
}
]
};
},
computed: {
is_own_item() {
let is_own_item = false;
if(this.item) {
if(this.item.hub_seller === hub.settings.hub_seller_name) {
is_own_item = true;
}
}
return is_own_item;
},
item_subtitle() {
@@ -272,11 +274,11 @@ export default {
},
edit_details() {
//
frappe.msgprint(__('This feature is under development...'));
},
unpublish_item() {
//
frappe.msgprint(__('This feature is under development...'));
}
}
}

View File

@@ -345,13 +345,14 @@ def set_tax_withholding_category(company):
if company and tds_account:
accounts = [dict(company=company, account=tds_account)]
fiscal_year = get_fiscal_year(today(), company=accounts[0].get('company'))[0]
fiscal_year = get_fiscal_year(today(), company=company)[0]
docs = get_tds_details(accounts, fiscal_year)
for d in docs:
try:
doc = frappe.get_doc(d)
doc.flags.ignore_permissions = True
doc.flags.ignore_mandatory = True
doc.insert()
except frappe.DuplicateEntryError:
doc = frappe.get_doc("Tax Withholding Category", d.get("name"))

View File

@@ -102,7 +102,8 @@ def get_party_details(party_type, party_list, doctype, party_details):
records = frappe.get_list(doctype, filters=filters, fields=fields, as_list=True)
for d in records:
details = party_details.get(d[0])
details.setdefault(frappe.scrub(doctype), []).append(d[1:])
if details:
details.setdefault(frappe.scrub(doctype), []).append(d[1:])
return party_details

View File

@@ -1,12 +1,13 @@
{
"add_total_row": 0,
"add_total_row": 1,
"creation": "2018-09-21 12:46:29.451048",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2018-09-21 12:46:29.451048",
"modified": "2019-02-12 14:30:40.043652",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Analytics",

View File

@@ -263,10 +263,13 @@ def install(country=None):
def set_more_defaults():
# Do more setup stuff that can be done here with no dependencies
# set default customer group and territory
selling_settings = frappe.get_doc("Selling Settings")
selling_settings.set_default_customer_group_and_territory()
selling_settings.cust_master_name = "Customer Name"
selling_settings.so_required = "No"
selling_settings.dn_required = "No"
selling_settings.allow_multiple_items = 1
selling_settings.sales_update_frequency = "Each Transaction"
selling_settings.save()
add_uom_data()
@@ -276,14 +279,6 @@ def set_more_defaults():
doc.set_default_fields()
doc.save()
selling_settings = frappe.get_doc("Selling Settings")
selling_settings.cust_master_name = "Customer Name"
selling_settings.so_required = "No"
selling_settings.dn_required = "No"
selling_settings.allow_multiple_items = 1
selling_settings.sales_update_frequency = "Each Transaction"
selling_settings.save()
buying_settings = frappe.get_doc("Buying Settings")
buying_settings.supp_master_name = "Supplier Name"
buying_settings.po_required = "No"

View File

@@ -13,7 +13,13 @@ def get_data(item_code=None, warehouse=None, item_group=None,
if warehouse:
filters.append(['warehouse', '=', warehouse])
if item_group:
filters.append(['item_group', '=', item_group])
lft, rgt = frappe.db.get_value("Item Group", item_group, ["lft", "rgt"])
items = frappe.db.sql_list("""
select i.name from `tabItem` i
where exists(select name from `tabItem Group`
where name=i.item_group and lft >=%s and rgt<=%s)
""", (lft, rgt))
filters.append(['item_code', 'in', items])
try:
# check if user has any restrictions based on user permissions on warehouse
if DatabaseQuery('Warehouse', user=frappe.session.user).build_match_conditions():

View File

@@ -700,15 +700,14 @@ class Item(WebsiteGenerator):
frappe.db.get_single_value('Item Variant Settings', 'do_not_update_variants'):
return
if self.has_variants:
updated = []
variants = frappe.db.get_all("Item", fields=["item_code"], filters={"variant_of": self.name})
for d in variants:
variant = frappe.get_doc("Item", d)
copy_attributes_to_variant(self, variant)
variant.save()
updated.append(d.item_code)
if updated:
frappe.msgprint(_("Item Variants {0} updated").format(", ".join(updated)))
if variants:
if len(variants) <= 30:
update_variants(variants, self, publish_progress=False)
frappe.msgprint(_("Item Variants updated"))
else:
frappe.enqueue("erpnext.stock.doctype.item.item.update_variants",
variants=variants, template=self, now=frappe.flags.in_test, timeout=600)
def validate_has_variants(self):
if not self.has_variants and frappe.db.get_value("Item", self.name, "has_variants"):
@@ -997,3 +996,13 @@ def get_item_attribute(parent, attribute_value=''):
return frappe.get_all("Item Attribute Value", fields = ["attribute_value"],
filters = {'parent': parent, 'attribute_value': ("like", "%%%s%%" % attribute_value)})
def update_variants(variants, template, publish_progress=True):
count=0
for d in variants:
variant = frappe.get_doc("Item", d)
copy_attributes_to_variant(template, variant)
variant.save()
count+=1
if publish_progress:
frappe.publish_progress(count*100/len(variants), title = _("Updating Variants..."))

View File

@@ -81,9 +81,9 @@ class MaterialRequest(BuyingController):
def set_title(self):
'''Set title as comma separated list of items'''
items = ', '.join([d.item_name for d in self.items][:4])
self.title = _('{0} for {1}'.format(self.material_request_type, items))[:100]
if not self.title:
items = ', '.join([d.item_name for d in self.items][:3])
self.title = _('{0} Request for {1}').format(self.material_request_type, items)[:100]
def on_submit(self):
# frappe.db.set(self, 'status', 'Submitted')

View File

@@ -293,8 +293,9 @@ class StockEntry(StockController):
total_completed_qty = flt(self.fg_completed_qty) + flt(prod_order.produced_qty)
completed_qty = d.completed_qty + (allowance_percentage/100 * d.completed_qty)
if total_completed_qty > flt(completed_qty):
frappe.throw(_("Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order # {3}. Please update operation status via Time Logs")
.format(d.idx, d.operation, total_completed_qty, self.work_order), OperationsNotCompleteError)
job_card = frappe.db.get_value('Job Card', {'operation_id': d.name}, 'name')
frappe.throw(_("Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order # {3}. Please update operation status via Job Card # {4}")
.format(d.idx, d.operation, total_completed_qty, self.work_order, job_card), OperationsNotCompleteError)
def check_duplicate_entry_for_work_order(self):
other_ste = [t[0] for t in frappe.db.get_values("Stock Entry", {
@@ -914,6 +915,11 @@ class StockEntry(StockController):
filters={'parent': self.work_order, 'item_code': item_code},
fields=["required_qty", "consumed_qty"]
)
if not req_items:
frappe.msgprint(_("Did not found transfered item {0} in Work Order {1}, the item not added in Stock Entry")
.format(item_code, self.work_order))
continue
req_qty = flt(req_items[0].required_qty)
req_qty_each = flt(req_qty / manufacturing_qty)
consumed_qty = flt(req_items[0].consumed_qty)

View File

@@ -259,6 +259,7 @@ class StockReconciliation(StockController):
def submit(self):
if len(self.items) > 100:
msgprint(_("The task has been enqueued as a background job. In case there is any issue on processing in background, the system will add a comment about the error on this Stock Reconciliation and revert to the Draft stage"))
self.queue_action('submit')
else:
self._submit()

View File

@@ -157,6 +157,8 @@ def get_children(doctype, parent=None, company=None, is_root=False):
# return warehouses
for wh in warehouses:
wh["balance"] = get_stock_value_from_bin(warehouse=wh.value)
if company:
wh["company_currency"] = frappe.db.get_value('Company', company, 'default_currency')
return warehouses
@frappe.whitelist()

View File

@@ -16,6 +16,9 @@ from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
from six import string_types, iteritems
sales_doctypes = ['Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice']
purchase_doctypes = ['Material Request', 'Supplier Quotation', 'Purchase Order', 'Purchase Receipt', 'Purchase Invoice']
@frappe.whitelist()
def get_item_details(args):
"""
@@ -228,7 +231,7 @@ def get_basic_details(args, item):
#Set the UOM to the Default Sales UOM or Default Purchase UOM if configured in the Item Master
if not args.uom:
if args.get('doctype') in ['Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice']:
if args.get('doctype') in sales_doctypes:
args.uom = item.sales_uom if item.sales_uom else item.stock_uom
elif (args.get('doctype') in ['Purchase Order', 'Purchase Receipt', 'Purchase Invoice']) or \
(args.get('doctype') == 'Material Request' and args.get('material_request_type') == 'Purchase'):
@@ -281,14 +284,15 @@ def get_basic_details(args, item):
out.conversion_factor = 1.0
else:
out.conversion_factor = args.conversion_factor or \
get_conversion_factor(item.item_code, args.uom).get("conversion_factor")
get_conversion_factor(item.name, args.uom).get("conversion_factor")
args.conversion_factor = out.conversion_factor
out.stock_qty = out.qty * out.conversion_factor
# calculate last purchase rate
from erpnext.buying.doctype.purchase_order.purchase_order import item_last_purchase_rate
out.last_purchase_rate = item_last_purchase_rate(args.name, args.conversion_rate, item.item_code, out.conversion_factor)
if args.get('doctype') in purchase_doctypes:
from erpnext.buying.doctype.purchase_order.purchase_order import item_last_purchase_rate
out.last_purchase_rate = item_last_purchase_rate(args.name, args.conversion_rate, item.name, out.conversion_factor)
# if default specified in item is for another company, fetch from company
for d in [

View File

@@ -1,12 +1,13 @@
{
"add_total_row": 0,
"add_total_row": 1,
"creation": "2018-10-08 12:11:32.133020",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2018-10-08 12:18:42.834270",
"modified": "2019-02-12 14:32:22.874082",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Analytics",

View File

@@ -173,15 +173,15 @@ def get_item_warehouse_map(filters, sle):
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
float_precision = cint(frappe.db.get_default("float_precision")) or 3
for key, val in iteritems(qty_dict):
@@ -189,7 +189,7 @@ def filter_items_with_no_transactions(iwb_map):
qty_dict[key] = val
if key != "val_rate" and val:
no_transactions = False
if no_transactions:
iwb_map.pop((company, item, warehouse))
@@ -216,20 +216,28 @@ def get_item_details(items, sle, filters):
if not items:
items = list(set([d.item_code for d in sle]))
if items:
cf_field = cf_join = ""
if filters.get("include_uom"):
cf_field = ", ucd.conversion_factor"
cf_join = "left join `tabUOM Conversion Detail` ucd on ucd.parent=item.name and ucd.uom=%(include_uom)s"
if not items:
return item_details
for item in frappe.db.sql("""
select item.name, item.item_name, item.description, item.item_group, item.brand, item.stock_uom{cf_field}
from `tabItem` item
cf_field = cf_join = ""
if filters.get("include_uom"):
cf_field = ", ucd.conversion_factor"
cf_join = "left join `tabUOM Conversion Detail` ucd on ucd.parent=item.name and ucd.uom='%s'" \
% frappe.db.escape(filters.get("include_uom"))
item_codes = ', '.join(['"' + frappe.db.escape(i, percent=False) + '"' for i in items])
res = frappe.db.sql("""
select
item.name, item.item_name, item.description, item.item_group, item.brand, item.stock_uom {cf_field}
from
`tabItem` item
{cf_join}
where item.name in ({names}) and ifnull(item.disabled, 0) = 0
""".format(cf_field=cf_field, cf_join=cf_join, names=', '.join(['"' + frappe.db.escape(i, percent=False) + '"' for i in items])),
{"include_uom": filters.get("include_uom")}, as_dict=1):
item_details.setdefault(item.name, item)
where
item.name in ({item_codes}) and ifnull(item.disabled, 0) = 0
""".format(cf_field=cf_field, cf_join=cf_join, item_codes=item_codes), as_dict=1)
for item in res:
item_details.setdefault(item.name, item)
if filters.get('show_variant_attributes', 0) == 1:
variant_values = get_variant_values_for(list(item_details))

View File

@@ -15,7 +15,7 @@
{{ chapter_button() }}
<p><a href="">Leave Chapter</a></p>
{% else %}
{% if frappe.local.request.method=='POST' %}
{% if request.method=='POST' %}
<p>Welcome to chapter {{ chapter.name }}!</p>
{{ chapter_button() }}
{% else %}