mirror of
https://github.com/frappe/erpnext.git
synced 2026-04-17 13:55:10 +00:00
Merge branch 'develop' into payments-based-dunning
This commit is contained in:
5
.github/helper/.flake8_strict
vendored
5
.github/helper/.flake8_strict
vendored
@@ -65,6 +65,11 @@ ignore =
|
||||
E713,
|
||||
E712,
|
||||
|
||||
enable-extensions =
|
||||
M90
|
||||
|
||||
select =
|
||||
M511
|
||||
|
||||
max-line-length = 200
|
||||
exclude=.github/helper/semgrep_rules,test_*.py
|
||||
|
||||
2
.github/workflows/ui-tests.yml
vendored
2
.github/workflows/ui-tests.yml
vendored
@@ -104,6 +104,8 @@ jobs:
|
||||
|
||||
- name: Build Assets
|
||||
run: cd ~/frappe-bench/ && bench build
|
||||
env:
|
||||
CI: Yes
|
||||
|
||||
- name: UI Tests
|
||||
run: cd ~/frappe-bench/ && bench --site test_site run-ui-tests erpnext --headless
|
||||
|
||||
@@ -20,7 +20,10 @@ repos:
|
||||
rev: 3.9.2
|
||||
hooks:
|
||||
- id: flake8
|
||||
args: ['--config', '.github/helper/.flake8_strict']
|
||||
additional_dependencies: [
|
||||
'flake8-mutable',
|
||||
]
|
||||
args: ['--select=M511', '--config', '.github/helper/.flake8_strict']
|
||||
exclude: ".*setup.py$"
|
||||
|
||||
- repo: https://github.com/timothycrosley/isort
|
||||
|
||||
@@ -52,21 +52,35 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
|
||||
|
||||
refresh() {
|
||||
this.frm.disable_save();
|
||||
this.frm.set_df_property('invoices', 'cannot_delete_rows', true);
|
||||
this.frm.set_df_property('payments', 'cannot_delete_rows', true);
|
||||
this.frm.set_df_property('allocation', 'cannot_delete_rows', true);
|
||||
|
||||
this.frm.set_df_property('invoices', 'cannot_add_rows', true);
|
||||
this.frm.set_df_property('payments', 'cannot_add_rows', true);
|
||||
this.frm.set_df_property('allocation', 'cannot_add_rows', true);
|
||||
|
||||
|
||||
if (this.frm.doc.receivable_payable_account) {
|
||||
this.frm.add_custom_button(__('Get Unreconciled Entries'), () =>
|
||||
this.frm.trigger("get_unreconciled_entries")
|
||||
);
|
||||
this.frm.change_custom_button_type('Get Unreconciled Entries', null, 'primary');
|
||||
}
|
||||
if (this.frm.doc.invoices.length && this.frm.doc.payments.length) {
|
||||
this.frm.add_custom_button(__('Allocate'), () =>
|
||||
this.frm.trigger("allocate")
|
||||
);
|
||||
this.frm.change_custom_button_type('Allocate', null, 'primary');
|
||||
this.frm.change_custom_button_type('Get Unreconciled Entries', null, 'default');
|
||||
}
|
||||
if (this.frm.doc.allocation.length) {
|
||||
this.frm.add_custom_button(__('Reconcile'), () =>
|
||||
this.frm.trigger("reconcile")
|
||||
);
|
||||
this.frm.change_custom_button_type('Reconcile', null, 'primary');
|
||||
this.frm.change_custom_button_type('Get Unreconciled Entries', null, 'default');
|
||||
this.frm.change_custom_button_type('Allocate', null, 'default');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,15 +12,16 @@
|
||||
"receivable_payable_account",
|
||||
"col_break1",
|
||||
"from_invoice_date",
|
||||
"to_invoice_date",
|
||||
"minimum_invoice_amount",
|
||||
"maximum_invoice_amount",
|
||||
"invoice_limit",
|
||||
"column_break_13",
|
||||
"from_payment_date",
|
||||
"to_payment_date",
|
||||
"minimum_invoice_amount",
|
||||
"minimum_payment_amount",
|
||||
"column_break_11",
|
||||
"to_invoice_date",
|
||||
"to_payment_date",
|
||||
"maximum_invoice_amount",
|
||||
"maximum_payment_amount",
|
||||
"column_break_13",
|
||||
"invoice_limit",
|
||||
"payment_limit",
|
||||
"bank_cash_account",
|
||||
"sec_break1",
|
||||
@@ -79,6 +80,7 @@
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:(doc.payments).length || (doc.invoices).length",
|
||||
"description": "If you need to reconcile particular transactions against each other, then please select accordingly. If not, all the transactions will be allocated in FIFO order.",
|
||||
"fieldname": "sec_break1",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Unreconciled Entries"
|
||||
@@ -163,6 +165,7 @@
|
||||
"label": "Maximum Payment Amount"
|
||||
},
|
||||
{
|
||||
"description": "System will fetch all the entries if limit value is zero.",
|
||||
"fieldname": "payment_limit",
|
||||
"fieldtype": "Int",
|
||||
"label": "Payment Limit"
|
||||
@@ -171,13 +174,17 @@
|
||||
"fieldname": "maximum_invoice_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Maximum Invoice Amount"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_11",
|
||||
"fieldtype": "Column Break"
|
||||
}
|
||||
],
|
||||
"hide_toolbar": 1,
|
||||
"icon": "icon-resize-horizontal",
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2021-08-30 13:05:51.977861",
|
||||
"modified": "2021-10-04 20:27:11.114194",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Reconciliation",
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
"section_break_6",
|
||||
"allocated_amount",
|
||||
"unreconciled_amount",
|
||||
"amount",
|
||||
"column_break_8",
|
||||
"amount",
|
||||
"is_advance",
|
||||
"section_break_5",
|
||||
"difference_amount",
|
||||
@@ -127,12 +127,13 @@
|
||||
"fieldname": "reference_row",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"label": "Reference Row"
|
||||
"label": "Reference Row",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-09-20 17:23:09.455803",
|
||||
"modified": "2021-10-06 11:48:59.616562",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Reconciliation Allocation",
|
||||
|
||||
@@ -33,7 +33,9 @@ class TestPOSProfile(unittest.TestCase):
|
||||
|
||||
frappe.db.sql("delete from `tabPOS Profile`")
|
||||
|
||||
def get_customers_list(pos_profile={}):
|
||||
def get_customers_list(pos_profile=None):
|
||||
if pos_profile is None:
|
||||
pos_profile = {}
|
||||
cond = "1=1"
|
||||
customer_groups = []
|
||||
if pos_profile.get('customer_groups'):
|
||||
|
||||
@@ -398,7 +398,9 @@ def get_qty_and_rate_for_other_item(doc, pr_doc, pricing_rules):
|
||||
pricing_rules[0].apply_rule_on_other_items = items
|
||||
return pricing_rules
|
||||
|
||||
def get_qty_amount_data_for_cumulative(pr_doc, doc, items=[]):
|
||||
def get_qty_amount_data_for_cumulative(pr_doc, doc, items=None):
|
||||
if items is None:
|
||||
items = []
|
||||
sum_qty, sum_amt = [0, 0]
|
||||
doctype = doc.get('parenttype') or doc.doctype
|
||||
|
||||
|
||||
@@ -69,7 +69,9 @@ class PromotionalScheme(Document):
|
||||
{'promotional_scheme': self.name}):
|
||||
frappe.delete_doc('Pricing Rule', rule.name)
|
||||
|
||||
def get_pricing_rules(doc, rules = {}):
|
||||
def get_pricing_rules(doc, rules=None):
|
||||
if rules is None:
|
||||
rules = {}
|
||||
new_doc = []
|
||||
for child_doc, fields in {'price_discount_slabs': price_discount_fields,
|
||||
'product_discount_slabs': product_discount_fields}.items():
|
||||
@@ -78,7 +80,9 @@ def get_pricing_rules(doc, rules = {}):
|
||||
|
||||
return new_doc
|
||||
|
||||
def _get_pricing_rules(doc, child_doc, discount_fields, rules = {}):
|
||||
def _get_pricing_rules(doc, child_doc, discount_fields, rules=None):
|
||||
if rules is None:
|
||||
rules = {}
|
||||
new_doc = []
|
||||
args = get_args_for_pricing_rule(doc)
|
||||
applicable_for = frappe.scrub(doc.get('applicable_for'))
|
||||
|
||||
@@ -139,9 +139,9 @@ def get_account_type_based_data(company, account_type, period_list, accumulated_
|
||||
data["total"] = total
|
||||
return data
|
||||
|
||||
def get_account_type_based_gl_data(company, start_date, end_date, account_type, filters={}):
|
||||
def get_account_type_based_gl_data(company, start_date, end_date, account_type, filters=None):
|
||||
cond = ""
|
||||
filters = frappe._dict(filters)
|
||||
filters = frappe._dict(filters or {})
|
||||
|
||||
if filters.include_default_book_entries:
|
||||
company_fb = frappe.db.get_value("Company", company, 'default_finance_book')
|
||||
|
||||
@@ -138,7 +138,9 @@ class Student(Document):
|
||||
enrollment.submit()
|
||||
return enrollment
|
||||
|
||||
def enroll_in_course(self, course_name, program_enrollment, enrollment_date=frappe.utils.datetime.datetime.now()):
|
||||
def enroll_in_course(self, course_name, program_enrollment, enrollment_date=None):
|
||||
if enrollment_date is None:
|
||||
enrollment_date = frappe.utils.datetime.datetime.now()
|
||||
try:
|
||||
enrollment = frappe.get_doc({
|
||||
"doctype": "Course Enrollment",
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
@@ -94,9 +93,11 @@ def get_events(start, end, filters=None):
|
||||
update={"allDay": 1})
|
||||
|
||||
|
||||
def is_holiday(holiday_list, date=today()):
|
||||
def is_holiday(holiday_list, date=None):
|
||||
"""Returns true if the given date is a holiday in the given holiday list
|
||||
"""
|
||||
if date is None:
|
||||
date = today()
|
||||
if holiday_list:
|
||||
return bool(frappe.get_all('Holiday List',
|
||||
dict(name=holiday_list, holiday_date=date)))
|
||||
|
||||
@@ -139,7 +139,7 @@ def get_shift_type_timing(shift_types):
|
||||
return shift_timing_map
|
||||
|
||||
|
||||
def get_employee_shift(employee, for_date=nowdate(), consider_default_shift=False, next_shift_direction=None):
|
||||
def get_employee_shift(employee, for_date=None, consider_default_shift=False, next_shift_direction=None):
|
||||
"""Returns a Shift Type for the given employee on the given date. (excluding the holidays)
|
||||
|
||||
:param employee: Employee for which shift is required.
|
||||
@@ -147,6 +147,8 @@ def get_employee_shift(employee, for_date=nowdate(), consider_default_shift=Fals
|
||||
:param consider_default_shift: If set to true, default shift is taken when no shift assignment is found.
|
||||
:param next_shift_direction: One of: None, 'forward', 'reverse'. Direction to look for next shift if shift not found on given date.
|
||||
"""
|
||||
if for_date is None:
|
||||
for_date = nowdate()
|
||||
default_shift = frappe.db.get_value('Employee', employee, 'default_shift')
|
||||
shift_type_name = None
|
||||
shift_assignment_details = frappe.db.get_value('Shift Assignment', {'employee':employee, 'start_date':('<=', for_date), 'docstatus': '1', 'status': "Active"}, ['shift_type', 'end_date'])
|
||||
@@ -200,9 +202,11 @@ def get_employee_shift(employee, for_date=nowdate(), consider_default_shift=Fals
|
||||
return get_shift_details(shift_type_name, for_date)
|
||||
|
||||
|
||||
def get_employee_shift_timings(employee, for_timestamp=now_datetime(), consider_default_shift=False):
|
||||
def get_employee_shift_timings(employee, for_timestamp=None, consider_default_shift=False):
|
||||
"""Returns previous shift, current/upcoming shift, next_shift for the given timestamp and employee
|
||||
"""
|
||||
if for_timestamp is None:
|
||||
for_timestamp = now_datetime()
|
||||
# write and verify a test case for midnight shift.
|
||||
prev_shift = curr_shift = next_shift = None
|
||||
curr_shift = get_employee_shift(employee, for_timestamp.date(), consider_default_shift, 'forward')
|
||||
@@ -220,7 +224,7 @@ def get_employee_shift_timings(employee, for_timestamp=now_datetime(), consider_
|
||||
return prev_shift, curr_shift, next_shift
|
||||
|
||||
|
||||
def get_shift_details(shift_type_name, for_date=nowdate()):
|
||||
def get_shift_details(shift_type_name, for_date=None):
|
||||
"""Returns Shift Details which contain some additional information as described below.
|
||||
'shift_details' contains the following keys:
|
||||
'shift_type' - Object of DocType Shift Type,
|
||||
@@ -234,6 +238,8 @@ def get_shift_details(shift_type_name, for_date=nowdate()):
|
||||
"""
|
||||
if not shift_type_name:
|
||||
return None
|
||||
if not for_date:
|
||||
for_date = nowdate()
|
||||
shift_type = frappe.get_doc('Shift Type', shift_type_name)
|
||||
start_datetime = datetime.combine(for_date, datetime.min.time()) + shift_type.start_time
|
||||
for_date = for_date + timedelta(days=1) if shift_type.start_time > shift_type.end_time else for_date
|
||||
|
||||
@@ -155,7 +155,11 @@ def get_designation_counts(designation, company):
|
||||
return employee_counts
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_active_staffing_plan_details(company, designation, from_date=getdate(nowdate()), to_date=getdate(nowdate())):
|
||||
def get_active_staffing_plan_details(company, designation, from_date=None, to_date=None):
|
||||
if from_date is None:
|
||||
from_date = getdate(nowdate())
|
||||
if to_date is None:
|
||||
to_date = getdate(nowdate())
|
||||
if not company or not designation:
|
||||
frappe.throw(_("Please select Company and Designation"))
|
||||
|
||||
|
||||
@@ -141,7 +141,6 @@ class TestSalarySlip(unittest.TestCase):
|
||||
create_salary_structure_assignment,
|
||||
)
|
||||
|
||||
no_of_days = self.get_no_of_days()
|
||||
# Payroll based on attendance
|
||||
frappe.db.set_value("Payroll Settings", None, "payroll_based_on", "Attendance")
|
||||
|
||||
@@ -168,9 +167,6 @@ class TestSalarySlip(unittest.TestCase):
|
||||
ss = make_salary_slip_for_payment_days_dependency_test("test_payment_days_based_component@salary.com", salary_structure.name)
|
||||
self.assertEqual(ss.absent_days, 1)
|
||||
|
||||
days_in_month = no_of_days[0]
|
||||
no_of_holidays = no_of_days[1]
|
||||
|
||||
ss.reload()
|
||||
payment_days_based_comp_amount = 0
|
||||
for component in ss.earnings:
|
||||
@@ -992,13 +988,14 @@ def make_salary_structure_for_payment_days_based_component_dependency():
|
||||
return salary_structure_doc
|
||||
|
||||
def make_salary_slip_for_payment_days_dependency_test(employee, salary_structure):
|
||||
employee = frappe.db.get_value("Employee", {
|
||||
"user_id": employee
|
||||
},
|
||||
employee = frappe.db.get_value(
|
||||
"Employee",
|
||||
{"user_id": employee},
|
||||
["name", "company", "employee_name"],
|
||||
as_dict=True)
|
||||
as_dict=True
|
||||
)
|
||||
|
||||
salary_slip_name = frappe.db.get_value("Salary Slip", {"employee": frappe.db.get_value("Employee", {"user_id": employee})})
|
||||
salary_slip_name = frappe.db.get_value("Salary Slip", {"employee": employee.name})
|
||||
|
||||
if not salary_slip_name:
|
||||
salary_slip = make_salary_slip(salary_structure, employee=employee.name)
|
||||
@@ -1009,4 +1006,4 @@ def make_salary_slip_for_payment_days_dependency_test(employee, salary_structure
|
||||
else:
|
||||
salary_slip = frappe.get_doc("Salary Slip", salary_slip_name)
|
||||
|
||||
return salary_slip
|
||||
return salary_slip
|
||||
|
||||
@@ -300,7 +300,7 @@ frappe.help.help_links["List/Sales Order"] = [
|
||||
},
|
||||
{
|
||||
label: "Recurring Sales Order",
|
||||
url: docsUrl + "user/manual/en/accounts/recurring-orders-and-invoices",
|
||||
url: docsUrl + "user/manual/en/accounts/articles/recurring-orders-and-invoices",
|
||||
},
|
||||
{
|
||||
label: "Applying Discount",
|
||||
@@ -397,7 +397,7 @@ frappe.help.help_links["List/Purchase Order"] = [
|
||||
},
|
||||
{
|
||||
label: "Recurring Purchase Order",
|
||||
url: docsUrl + "user/manual/en/accounts/recurring-orders-and-invoices",
|
||||
url: docsUrl + "user/manual/en/accounts/articles/recurring-orders-and-invoices",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -420,7 +420,7 @@ frappe.help.help_links["Form/Purchase Order"] = [
|
||||
},
|
||||
{
|
||||
label: "Recurring Purchase Order",
|
||||
url: docsUrl + "user/manual/en/accounts/recurring-orders-and-invoices",
|
||||
url: docsUrl + "user/manual/en/accounts/articles/recurring-orders-and-invoices",
|
||||
},
|
||||
{
|
||||
label: "Subcontracting",
|
||||
@@ -552,7 +552,7 @@ frappe.help.help_links["Form/Sales Invoice"] = [
|
||||
},
|
||||
{
|
||||
label: "Accounts Opening Balance",
|
||||
url: docsUrl + "user/manual/en/accounts/opening-accounts",
|
||||
url: docsUrl + "user/manual/en/accounts/opening-balance",
|
||||
},
|
||||
{
|
||||
label: "Sales Return",
|
||||
@@ -604,11 +604,11 @@ frappe.help.help_links["List/Purchase Invoice"] = [
|
||||
},
|
||||
{
|
||||
label: "Accounts Opening Balance",
|
||||
url: docsUrl + "user/manual/en/accounts/opening-accounts",
|
||||
url: docsUrl + "user/manual/en/accounts/opening-balance",
|
||||
},
|
||||
{
|
||||
label: "Recurring Purchase Invoice",
|
||||
url: docsUrl + "user/manual/en/accounts/recurring-orders-and-invoices",
|
||||
url: docsUrl + "user/manual/en/accounts/articles/recurring-orders-and-invoices",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -623,7 +623,7 @@ frappe.help.help_links["List/Journal Entry"] = [
|
||||
},
|
||||
{
|
||||
label: "Accounts Opening Balance",
|
||||
url: docsUrl + "user/manual/en/accounts/opening-accounts",
|
||||
url: docsUrl + "user/manual/en/accounts/opening-balance",
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -712,6 +712,7 @@ erpnext.utils.map_current_doc = function(opts) {
|
||||
allow_child_item_selection: opts.allow_child_item_selection,
|
||||
child_fieldname: opts.child_fielname,
|
||||
child_columns: opts.child_columns,
|
||||
size: opts.size,
|
||||
action: function(selections, args) {
|
||||
let values = selections;
|
||||
if (values.length === 0) {
|
||||
|
||||
@@ -46,43 +46,6 @@ frappe.ui.form.on("Company", {
|
||||
});
|
||||
},
|
||||
|
||||
change_abbreviation(frm) {
|
||||
var dialog = new frappe.ui.Dialog({
|
||||
title: "Replace Abbr",
|
||||
fields: [
|
||||
{"fieldtype": "Data", "label": "New Abbreviation", "fieldname": "new_abbr",
|
||||
"reqd": 1 },
|
||||
{"fieldtype": "Button", "label": "Update", "fieldname": "update"},
|
||||
]
|
||||
});
|
||||
|
||||
dialog.fields_dict.update.$input.click(function() {
|
||||
var args = dialog.get_values();
|
||||
if (!args) return;
|
||||
frappe.show_alert(__("Update in progress. It might take a while."));
|
||||
return frappe.call({
|
||||
method: "erpnext.setup.doctype.company.company.enqueue_replace_abbr",
|
||||
args: {
|
||||
"company": frm.doc.name,
|
||||
"old": frm.doc.abbr,
|
||||
"new": args.new_abbr
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.exc) {
|
||||
frappe.msgprint(__("There were errors."));
|
||||
return;
|
||||
} else {
|
||||
frm.set_value("abbr", args.new_abbr);
|
||||
}
|
||||
dialog.hide();
|
||||
frm.refresh();
|
||||
},
|
||||
btn: this
|
||||
});
|
||||
});
|
||||
dialog.show();
|
||||
},
|
||||
|
||||
company_name: function(frm) {
|
||||
if(frm.doc.__islocal) {
|
||||
// add missing " " arg in split method
|
||||
@@ -164,10 +127,6 @@ frappe.ui.form.on("Company", {
|
||||
}, __('Manage'));
|
||||
}
|
||||
}
|
||||
|
||||
frm.add_custom_button(__('Change Abbreviation'), () => {
|
||||
frm.trigger('change_abbreviation');
|
||||
}, __('Manage'));
|
||||
}
|
||||
|
||||
erpnext.company.set_chart_of_accounts_options(frm.doc);
|
||||
|
||||
@@ -125,7 +125,8 @@
|
||||
"label": "Abbr",
|
||||
"oldfieldname": "abbr",
|
||||
"oldfieldtype": "Data",
|
||||
"reqd": 1
|
||||
"reqd": 1,
|
||||
"set_only_once": 1
|
||||
},
|
||||
{
|
||||
"bold": 1,
|
||||
@@ -747,10 +748,11 @@
|
||||
"image_field": "company_logo",
|
||||
"is_tree": 1,
|
||||
"links": [],
|
||||
"modified": "2021-07-12 11:27:06.353860",
|
||||
"modified": "2021-10-04 12:09:25.833133",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Setup",
|
||||
"name": "Company",
|
||||
"naming_rule": "By fieldname",
|
||||
"nsm_parent_field": "parent_company",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
@@ -808,4 +810,4 @@
|
||||
"sort_field": "modified",
|
||||
"sort_order": "ASC",
|
||||
"track_changes": 1
|
||||
}
|
||||
}
|
||||
@@ -399,44 +399,6 @@ class Company(NestedSet):
|
||||
if not frappe.db.get_value('GL Entry', {'company': self.name}):
|
||||
frappe.db.sql("delete from `tabProcess Deferred Accounting` where company=%s", self.name)
|
||||
|
||||
@frappe.whitelist()
|
||||
def enqueue_replace_abbr(company, old, new):
|
||||
kwargs = dict(queue="long", company=company, old=old, new=new)
|
||||
frappe.enqueue('erpnext.setup.doctype.company.company.replace_abbr', **kwargs)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def replace_abbr(company, old, new):
|
||||
new = new.strip()
|
||||
if not new:
|
||||
frappe.throw(_("Abbr can not be blank or space"))
|
||||
|
||||
frappe.only_for("System Manager")
|
||||
|
||||
def _rename_record(doc):
|
||||
parts = doc[0].rsplit(" - ", 1)
|
||||
if len(parts) == 1 or parts[1].lower() == old.lower():
|
||||
frappe.rename_doc(dt, doc[0], parts[0] + " - " + new, force=True)
|
||||
|
||||
def _rename_records(dt):
|
||||
# rename is expensive so let's be economical with memory usage
|
||||
doc = (d for d in frappe.db.sql("select name from `tab%s` where company=%s" % (dt, '%s'), company))
|
||||
for d in doc:
|
||||
_rename_record(d)
|
||||
try:
|
||||
frappe.db.auto_commit_on_many_writes = 1
|
||||
for dt in ["Warehouse", "Account", "Cost Center", "Department",
|
||||
"Sales Taxes and Charges Template", "Purchase Taxes and Charges Template"]:
|
||||
_rename_records(dt)
|
||||
frappe.db.commit()
|
||||
frappe.db.set_value("Company", company, "abbr", new)
|
||||
|
||||
except Exception:
|
||||
frappe.log_error(title=_('Abbreviation Rename Error'))
|
||||
finally:
|
||||
frappe.db.auto_commit_on_many_writes = 0
|
||||
|
||||
|
||||
def get_name_with_abbr(name, company):
|
||||
company_abbr = frappe.get_cached_value('Company', company, "abbr")
|
||||
parts = name.split(" - ")
|
||||
|
||||
@@ -296,7 +296,7 @@ def make_purchase_order(source_name, target_doc=None, args=None):
|
||||
|
||||
return d.ordered_qty < d.stock_qty and child_filter
|
||||
|
||||
doclist = get_mapped_doc("Material Request", source_name, {
|
||||
doclist = get_mapped_doc("Material Request", source_name, {
|
||||
"Material Request": {
|
||||
"doctype": "Purchase Order",
|
||||
"validation": {
|
||||
@@ -323,7 +323,7 @@ def make_purchase_order(source_name, target_doc=None, args=None):
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_request_for_quotation(source_name, target_doc=None):
|
||||
doclist = get_mapped_doc("Material Request", source_name, {
|
||||
doclist = get_mapped_doc("Material Request", source_name, {
|
||||
"Material Request": {
|
||||
"doctype": "Request for Quotation",
|
||||
"validation": {
|
||||
|
||||
@@ -611,7 +611,9 @@ def get_pos_reserved_serial_nos(filters):
|
||||
|
||||
return reserved_sr_nos
|
||||
|
||||
def fetch_serial_numbers(filters, qty, do_not_include=[]):
|
||||
def fetch_serial_numbers(filters, qty, do_not_include=None):
|
||||
if do_not_include is None:
|
||||
do_not_include = []
|
||||
batch_join_selection = ""
|
||||
batch_no_condition = ""
|
||||
batch_nos = filters.get("batch_no")
|
||||
|
||||
@@ -382,7 +382,7 @@ def get_basic_details(args, item, overwrite_warehouse=True):
|
||||
|
||||
return out
|
||||
|
||||
def get_item_warehouse(item, args, overwrite_warehouse, defaults={}):
|
||||
def get_item_warehouse(item, args, overwrite_warehouse, defaults=None):
|
||||
if not defaults:
|
||||
defaults = frappe._dict({
|
||||
'item_defaults' : get_item_defaults(item.name, args.company),
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import json
|
||||
from math import ceil
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
@@ -149,11 +150,16 @@ def create_material_request(material_requests):
|
||||
conversion_factor = frappe.db.get_value("UOM Conversion Detail",
|
||||
{'parent': item.name, 'uom': uom}, 'conversion_factor') or 1.0
|
||||
|
||||
must_be_whole_number = frappe.db.get_value("UOM", uom, "must_be_whole_number", cache=True)
|
||||
qty = d.reorder_qty / conversion_factor
|
||||
if must_be_whole_number:
|
||||
qty = ceil(qty)
|
||||
|
||||
mr.append("items", {
|
||||
"doctype": "Material Request Item",
|
||||
"item_code": d.item_code,
|
||||
"schedule_date": add_days(nowdate(),cint(item.lead_time_days)),
|
||||
"qty": d.reorder_qty / conversion_factor,
|
||||
"qty": qty,
|
||||
"uom": uom,
|
||||
"stock_uom": item.stock_uom,
|
||||
"warehouse": d.warehouse,
|
||||
|
||||
Reference in New Issue
Block a user