Merge branch 'master' into develop
This commit is contained in:
commit
5fa2adcca9
@ -4,7 +4,7 @@ import inspect
|
|||||||
import frappe
|
import frappe
|
||||||
from erpnext.hooks import regional_overrides
|
from erpnext.hooks import regional_overrides
|
||||||
|
|
||||||
__version__ = '9.1.5'
|
__version__ = '9.1.6'
|
||||||
|
|
||||||
def get_default_company(user=None):
|
def get_default_company(user=None):
|
||||||
'''Get default company for user'''
|
'''Get default company for user'''
|
||||||
|
@ -486,17 +486,21 @@ def submit_invoice(si_doc, name, doc, name_list):
|
|||||||
if frappe.message_log: frappe.message_log.pop()
|
if frappe.message_log: frappe.message_log.pop()
|
||||||
frappe.db.rollback()
|
frappe.db.rollback()
|
||||||
frappe.log_error(frappe.get_traceback())
|
frappe.log_error(frappe.get_traceback())
|
||||||
name_list = save_invoice(e, si_doc, name, name_list)
|
name_list = save_invoice(doc, name, name_list)
|
||||||
|
|
||||||
return name_list
|
return name_list
|
||||||
|
|
||||||
def save_invoice(e, si_doc, name, name_list):
|
def save_invoice(doc, name, name_list):
|
||||||
try:
|
try:
|
||||||
if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}):
|
if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}):
|
||||||
si_doc.docstatus = 0
|
si = frappe.new_doc('Sales Invoice')
|
||||||
si_doc.flags.ignore_mandatory = True
|
si.update(doc)
|
||||||
si_doc.due_date = si_doc.posting_date
|
si.set_posting_time = 1
|
||||||
si_doc.insert()
|
si.customer = get_customer_id(doc)
|
||||||
|
si.due_date = doc.get('posting_date')
|
||||||
|
si.flags.ignore_mandatory = True
|
||||||
|
si.insert(ignore_permissions=True)
|
||||||
|
frappe.db.commit()
|
||||||
name_list.append(name)
|
name_list.append(name)
|
||||||
except Exception:
|
except Exception:
|
||||||
frappe.log_error(frappe.get_traceback())
|
frappe.log_error(frappe.get_traceback())
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
import unittest, copy
|
import unittest, copy, time
|
||||||
from frappe.utils import nowdate, add_days, flt
|
from frappe.utils import nowdate, add_days, flt, cint
|
||||||
from frappe.model.dynamic_links import get_dynamic_link_map
|
from frappe.model.dynamic_links import get_dynamic_link_map
|
||||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
|
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
|
||||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice
|
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice
|
||||||
@ -665,6 +665,47 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
self.pos_gl_entry(si, pos, 330)
|
self.pos_gl_entry(si, pos, 330)
|
||||||
|
|
||||||
|
def test_make_pos_invoice_in_draft(self):
|
||||||
|
from erpnext.accounts.doctype.sales_invoice.pos import make_invoice
|
||||||
|
from erpnext.stock.doctype.item.test_item import make_item
|
||||||
|
|
||||||
|
set_perpetual_inventory()
|
||||||
|
|
||||||
|
allow_negative_stock = frappe.db.get_single_value('Stock Settings', 'allow_negative_stock')
|
||||||
|
if allow_negative_stock:
|
||||||
|
frappe.db.set_value('Stock Settings', None, 'allow_negative_stock', 0)
|
||||||
|
|
||||||
|
make_pos_profile()
|
||||||
|
timestamp = cint(time.time())
|
||||||
|
|
||||||
|
item = make_item("_Test POS Item")
|
||||||
|
pos = copy.deepcopy(test_records[1])
|
||||||
|
pos['items'][0]['item_code'] = item.name
|
||||||
|
pos["is_pos"] = 1
|
||||||
|
pos["offline_pos_name"] = timestamp
|
||||||
|
pos["update_stock"] = 1
|
||||||
|
pos["payments"] = [{'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 300},
|
||||||
|
{'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 330}]
|
||||||
|
|
||||||
|
invoice_data = [{timestamp: pos}]
|
||||||
|
si = make_invoice(invoice_data).get('invoice')
|
||||||
|
self.assertEquals(si[0], timestamp)
|
||||||
|
|
||||||
|
sales_invoice = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': timestamp})
|
||||||
|
self.assertEquals(sales_invoice[0].docstatus, 0)
|
||||||
|
|
||||||
|
timestamp = cint(time.time())
|
||||||
|
pos["offline_pos_name"] = timestamp
|
||||||
|
invoice_data = [{timestamp: pos}]
|
||||||
|
si1 = make_invoice(invoice_data).get('invoice')
|
||||||
|
self.assertEquals(si1[0], timestamp)
|
||||||
|
|
||||||
|
sales_invoice1 = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': timestamp})
|
||||||
|
self.assertEquals(sales_invoice1[0].docstatus, 0)
|
||||||
|
|
||||||
|
if allow_negative_stock:
|
||||||
|
frappe.db.set_value('Stock Settings', None, 'allow_negative_stock', 1)
|
||||||
|
|
||||||
def pos_gl_entry(self, si, pos, cash_amount):
|
def pos_gl_entry(self, si, pos, cash_amount):
|
||||||
# check stock ledger entries
|
# check stock ledger entries
|
||||||
sle = frappe.db.sql("""select * from `tabStock Ledger Entry`
|
sle = frappe.db.sql("""select * from `tabStock Ledger Entry`
|
||||||
|
@ -107,6 +107,8 @@ class GrossProfitGenerator(object):
|
|||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
self.grouped = {}
|
self.grouped = {}
|
||||||
|
self.grouped_data = []
|
||||||
|
|
||||||
for row in self.si_list:
|
for row in self.si_list:
|
||||||
if self.skip_row(row, self.product_bundles):
|
if self.skip_row(row, self.product_bundles):
|
||||||
continue
|
continue
|
||||||
@ -150,7 +152,6 @@ class GrossProfitGenerator(object):
|
|||||||
|
|
||||||
def get_average_rate_based_on_group_by(self):
|
def get_average_rate_based_on_group_by(self):
|
||||||
# sum buying / selling totals for group
|
# sum buying / selling totals for group
|
||||||
self.grouped_data = []
|
|
||||||
for key in self.grouped.keys():
|
for key in self.grouped.keys():
|
||||||
if self.filters.get("group_by") != "Invoice":
|
if self.filters.get("group_by") != "Invoice":
|
||||||
for i, row in enumerate(self.grouped[key]):
|
for i, row in enumerate(self.grouped[key]):
|
||||||
|
@ -816,7 +816,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-07-21 14:06:46.309322",
|
"modified": "2017-10-17 17:27:06.281494",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Request for Quotation",
|
"name": "Request for Quotation",
|
||||||
@ -903,26 +903,6 @@
|
|||||||
"submit": 0,
|
"submit": 0,
|
||||||
"write": 0
|
"write": 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"amend": 0,
|
|
||||||
"apply_user_permissions": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 0,
|
|
||||||
"delete": 0,
|
|
||||||
"email": 1,
|
|
||||||
"export": 0,
|
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"report": 1,
|
|
||||||
"role": "Supplier",
|
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 0,
|
|
||||||
"submit": 0,
|
|
||||||
"write": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"amend": 0,
|
"amend": 0,
|
||||||
"apply_user_permissions": 0,
|
"apply_user_permissions": 0,
|
||||||
|
@ -205,9 +205,10 @@ def copy_attributes_to_variant(item, variant):
|
|||||||
|
|
||||||
if item.variant_based_on=='Item Attribute':
|
if item.variant_based_on=='Item Attribute':
|
||||||
if variant.attributes:
|
if variant.attributes:
|
||||||
variant.description += "\n"
|
if not variant.description:
|
||||||
for d in variant.attributes:
|
variant.description += "\n"
|
||||||
variant.description += "<div>" + d.attribute + ": " + cstr(d.attribute_value) + "</div>"
|
for d in variant.attributes:
|
||||||
|
variant.description += "<div>" + d.attribute + ": " + cstr(d.attribute_value) + "</div>"
|
||||||
|
|
||||||
def make_variant_item_code(template_item_code, template_item_name, variant):
|
def make_variant_item_code(template_item_code, template_item_name, variant):
|
||||||
"""Uses template's item code and abbreviations to make variant's item code"""
|
"""Uses template's item code and abbreviations to make variant's item code"""
|
||||||
|
@ -78,7 +78,7 @@ def create_invoice(company, patient, physician, consultation_id):
|
|||||||
create_invoice_items(physician, sales_invoice, company)
|
create_invoice_items(physician, sales_invoice, company)
|
||||||
|
|
||||||
sales_invoice.save(ignore_permissions=True)
|
sales_invoice.save(ignore_permissions=True)
|
||||||
frappe.db.sql(_("""update tabConsultation set invoice='{0}' where name='{1}'""").format(sales_invoice.name, consultation_id))
|
frappe.db.sql("""update tabConsultation set invoice=%s where name=%s""", (sales_invoice.name, consultation_id))
|
||||||
appointment = frappe.db.get_value("Consultation", consultation_id, "appointment")
|
appointment = frappe.db.get_value("Consultation", consultation_id, "appointment")
|
||||||
if appointment:
|
if appointment:
|
||||||
frappe.db.set_value("Patient Appointment", appointment, "sales_invoice", sales_invoice.name)
|
frappe.db.set_value("Patient Appointment", appointment, "sales_invoice", sales_invoice.name)
|
||||||
|
@ -291,5 +291,5 @@ def create_invoice(company, patient, lab_tests, prescriptions):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_lab_test_prescribed(patient):
|
def get_lab_test_prescribed(patient):
|
||||||
return frappe.db.sql(_("""select cp.name, cp.test_code, cp.parent, cp.invoice, ct.physician, ct.consultation_date from tabConsultation ct,
|
return frappe.db.sql("""select cp.name, cp.test_code, cp.parent, cp.invoice, ct.physician, ct.consultation_date from tabConsultation ct,
|
||||||
`tabLab Prescription` cp where ct.patient='{0}' and cp.parent=ct.name and cp.test_created=0""").format(patient))
|
`tabLab Prescription` cp where ct.patient=%s and cp.parent=ct.name and cp.test_created=0""", (patient))
|
||||||
|
@ -111,10 +111,10 @@ def make_invoice(patient, company):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_patient_detail(patient, company=None):
|
def get_patient_detail(patient, company=None):
|
||||||
patient_dict = frappe.db.sql(_("""select * from tabPatient where name='{0}'""").format(patient), as_dict=1)
|
patient_dict = frappe.db.sql("""select * from tabPatient where name=%s""", (patient), as_dict=1)
|
||||||
if not patient_dict:
|
if not patient_dict:
|
||||||
frappe.throw("Patient not found")
|
frappe.throw("Patient not found")
|
||||||
vital_sign = frappe.db.sql(_("""select * from `tabVital Signs` where patient='{0}' order by signs_date desc limit 1""").format(patient), as_dict=1)
|
vital_sign = frappe.db.sql("""select * from `tabVital Signs` where patient=%s order by signs_date desc limit 1""", (patient), as_dict=1)
|
||||||
|
|
||||||
details = patient_dict[0]
|
details = patient_dict[0]
|
||||||
if vital_sign:
|
if vital_sign:
|
||||||
|
@ -125,7 +125,7 @@ def create_invoice(company, physician, patient, appointment_id, appointment_date
|
|||||||
create_invoice_items(appointment_id, physician, company, sales_invoice)
|
create_invoice_items(appointment_id, physician, company, sales_invoice)
|
||||||
|
|
||||||
sales_invoice.save(ignore_permissions=True)
|
sales_invoice.save(ignore_permissions=True)
|
||||||
frappe.db.sql(_("""update `tabPatient Appointment` set sales_invoice='{0}' where name='{1}'""").format(sales_invoice.name, appointment_id))
|
frappe.db.sql("""update `tabPatient Appointment` set sales_invoice=%s where name=%s""", (sales_invoice.name, appointment_id))
|
||||||
frappe.db.set_value("Fee Validity", fee_validity.name, "ref_invoice", sales_invoice.name)
|
frappe.db.set_value("Fee Validity", fee_validity.name, "ref_invoice", sales_invoice.name)
|
||||||
consultation = frappe.db.exists({
|
consultation = frappe.db.exists({
|
||||||
"doctype": "Consultation",
|
"doctype": "Consultation",
|
||||||
|
@ -147,22 +147,28 @@ class BOM(WebsiteGenerator):
|
|||||||
if arg.get('scrap_items'):
|
if arg.get('scrap_items'):
|
||||||
rate = self.get_valuation_rate(arg)
|
rate = self.get_valuation_rate(arg)
|
||||||
elif arg:
|
elif arg:
|
||||||
if self.rm_cost_as_per == 'Valuation Rate':
|
if arg.get('bom_no') and self.set_rate_of_sub_assembly_item_based_on_bom:
|
||||||
rate = self.get_valuation_rate(arg)
|
|
||||||
elif self.rm_cost_as_per == 'Last Purchase Rate':
|
|
||||||
rate = arg['last_purchase_rate'] \
|
|
||||||
or frappe.db.get_value("Item", arg['item_code'], "last_purchase_rate")
|
|
||||||
elif self.rm_cost_as_per == "Price List":
|
|
||||||
if not self.buying_price_list:
|
|
||||||
frappe.throw(_("Please select Price List"))
|
|
||||||
rate = frappe.db.get_value("Item Price",
|
|
||||||
{"price_list": self.buying_price_list, "item_code": arg["item_code"]}, "price_list_rate")
|
|
||||||
price_list_currency = frappe.db.get_value("Price List", self.buying_price_list, "currency")
|
|
||||||
if price_list_currency != self.company_currency():
|
|
||||||
rate = flt(rate * self.conversion_rate)
|
|
||||||
|
|
||||||
if arg['bom_no'] and (not rate or self.set_rate_of_sub_assembly_item_based_on_bom):
|
|
||||||
rate = self.get_bom_unitcost(arg['bom_no'])
|
rate = self.get_bom_unitcost(arg['bom_no'])
|
||||||
|
else:
|
||||||
|
if self.rm_cost_as_per == 'Valuation Rate':
|
||||||
|
rate = self.get_valuation_rate(arg)
|
||||||
|
elif self.rm_cost_as_per == 'Last Purchase Rate':
|
||||||
|
rate = arg.get('last_purchase_rate') \
|
||||||
|
or frappe.db.get_value("Item", arg['item_code'], "last_purchase_rate")
|
||||||
|
elif self.rm_cost_as_per == "Price List":
|
||||||
|
if not self.buying_price_list:
|
||||||
|
frappe.throw(_("Please select Price List"))
|
||||||
|
rate = frappe.db.get_value("Item Price", {"price_list": self.buying_price_list,
|
||||||
|
"item_code": arg["item_code"]}, "price_list_rate")
|
||||||
|
|
||||||
|
price_list_currency = frappe.db.get_value("Price List",
|
||||||
|
self.buying_price_list, "currency")
|
||||||
|
if price_list_currency != self.company_currency():
|
||||||
|
rate = flt(rate * self.conversion_rate)
|
||||||
|
|
||||||
|
if not rate:
|
||||||
|
frappe.msgprint(_("{0} not found for Item {1}")
|
||||||
|
.format(self.rm_cost_as_per, arg["item_code"]))
|
||||||
|
|
||||||
return flt(rate)
|
return flt(rate)
|
||||||
|
|
||||||
|
@ -452,3 +452,4 @@ erpnext.patches.v9_0.fix_subscription_next_date
|
|||||||
erpnext.patches.v9_0.set_schedule_date_for_material_request_and_purchase_order
|
erpnext.patches.v9_0.set_schedule_date_for_material_request_and_purchase_order
|
||||||
erpnext.patches.v9_0.student_admission_childtable_migrate
|
erpnext.patches.v9_0.student_admission_childtable_migrate
|
||||||
erpnext.patches.v9_0.add_healthcare_domain
|
erpnext.patches.v9_0.add_healthcare_domain
|
||||||
|
erpnext.patches.v9_0.set_variant_item_description
|
||||||
|
45
erpnext/patches/v9_0/set_variant_item_description.py
Normal file
45
erpnext/patches/v9_0/set_variant_item_description.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import frappe
|
||||||
|
from frappe.utils import cstr
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
'''
|
||||||
|
Issue:
|
||||||
|
While copying data from template item to variant item,
|
||||||
|
the system appending description multiple times to the respective variant.
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
Check variant description,
|
||||||
|
if variant have user defined description remove all system appended descriptions
|
||||||
|
else replace multiple system generated descriptions with single description
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
1. Get all variant items
|
||||||
|
2. Create system generated variant description
|
||||||
|
3. If variant have user defined description, remove all system generated descriptions
|
||||||
|
4. If variant description only contains system generated description,
|
||||||
|
replace multiple descriptions by new description.
|
||||||
|
'''
|
||||||
|
for item in frappe.db.sql(""" select name from tabItem
|
||||||
|
where ifnull(variant_of, '') != '' """,as_dict=1):
|
||||||
|
variant = frappe.get_doc("Item", item.name)
|
||||||
|
temp_variant_description = '\n'
|
||||||
|
|
||||||
|
if variant.attributes:
|
||||||
|
for d in variant.attributes:
|
||||||
|
temp_variant_description += "<div>" + d.attribute + ": " + cstr(d.attribute_value) + "</div>"
|
||||||
|
|
||||||
|
variant_description = variant.description.replace(temp_variant_description, '').rstrip()
|
||||||
|
if variant_description:
|
||||||
|
splitted_desc = variant.description.strip().split(temp_variant_description)
|
||||||
|
|
||||||
|
if len(splitted_desc) > 2:
|
||||||
|
if splitted_desc[0] == '':
|
||||||
|
variant_description = temp_variant_description + variant_description
|
||||||
|
elif splitted_desc[1] == '' or splitted_desc[1] == '\n':
|
||||||
|
variant_description += temp_variant_description
|
||||||
|
variant.db_set('description', variant_description, update_modified=False)
|
||||||
|
else:
|
||||||
|
variant.db_set('description', variant_description, update_modified=False)
|
||||||
|
|
||||||
|
else:
|
||||||
|
variant.db_set('description', temp_variant_description, update_modified=False)
|
@ -159,9 +159,14 @@ frappe.ui.form.on("Timesheet Detail", {
|
|||||||
});
|
});
|
||||||
|
|
||||||
var calculate_end_time = function(frm, cdt, cdn) {
|
var calculate_end_time = function(frm, cdt, cdn) {
|
||||||
var child = locals[cdt][cdn];
|
let child = locals[cdt][cdn];
|
||||||
|
|
||||||
var d = moment(child.from_time);
|
if(!child.from_time) {
|
||||||
|
// if from_time value is not available then set the current datetime
|
||||||
|
frappe.model.set_value(cdt, cdn, "from_time", frappe.datetime.get_datetime_as_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let d = moment(child.from_time);
|
||||||
if(child.hours) {
|
if(child.hours) {
|
||||||
d.add(child.hours, "hours");
|
d.add(child.hours, "hours");
|
||||||
frm._setting_hours = true;
|
frm._setting_hours = true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user