You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

174 lines
5.7 KiB

  1. # Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
  2. #
  3. # MIT License (MIT)
  4. #
  5. # Permission is hereby granted, free of charge, to any person obtaining a
  6. # copy of this software and associated documentation files (the "Software"),
  7. # to deal in the Software without restriction, including without limitation
  8. # the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. # and/or sell copies of the Software, and to permit persons to whom the
  10. # Software is furnished to do so, subject to the following conditions:
  11. #
  12. # The above copyright notice and this permission notice shall be included in
  13. # all copies or substantial portions of the Software.
  14. #
  15. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  16. # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  17. # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  18. # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  19. # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
  20. # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. #
  22. from __future__ import unicode_literals
  23. import webnotes
  24. from webnotes import msgprint
  25. import json
  26. import csv, cStringIO
  27. from webnotes.utils import encode, cstr, cint, flt
  28. def read_csv_content_from_uploaded_file(ignore_encoding=False):
  29. from webnotes.utils.file_manager import get_uploaded_content
  30. fname, fcontent = get_uploaded_content()
  31. return read_csv_content(fcontent, ignore_encoding)
  32. def read_csv_content_from_attached_file(doc):
  33. fileid = webnotes.conn.get_value("File Data", {"attached_to_doctype": doc.doctype,
  34. "attached_to_name":doc.name}, "name")
  35. if not fileid:
  36. msgprint("File not attached!")
  37. raise Exception
  38. try:
  39. from webnotes.utils.file_manager import get_file
  40. fname, fcontent = get_file(fileid)
  41. return read_csv_content(fcontent, webnotes.form_dict.get('ignore_encoding_errors'))
  42. except Exception, e:
  43. webnotes.msgprint("""Unable to open attached file. Please try again.""")
  44. raise Exception
  45. def read_csv_content(fcontent, ignore_encoding=False):
  46. rows = []
  47. try:
  48. reader = csv.reader(fcontent.splitlines())
  49. # decode everything
  50. csvrows = [[val for val in row] for row in reader]
  51. for row in csvrows:
  52. newrow = []
  53. for val in row:
  54. if ignore_encoding:
  55. newrow.append(cstr(val.strip()))
  56. else:
  57. try:
  58. newrow.append(unicode(val.strip(), 'utf-8'))
  59. except UnicodeDecodeError, e:
  60. webnotes.msgprint("""Some character(s) in row #%s, column #%s are
  61. not readable by utf-8. Ignoring them. If you are importing a non
  62. english language, please make sure your file is saved in the 'utf-8'
  63. encoding.""" % (csvrows.index(row)+1, row.index(val)+1))
  64. raise Exception
  65. rows.append(newrow)
  66. return rows
  67. except Exception, e:
  68. webnotes.msgprint("Not a valid Comma Separated Value (CSV File)")
  69. raise e
  70. @webnotes.whitelist()
  71. def send_csv_to_client(args):
  72. if isinstance(args, basestring):
  73. args = json.loads(args)
  74. args = webnotes._dict(args)
  75. webnotes.response["result"] = cstr(to_csv(args.data))
  76. webnotes.response["doctype"] = args.filename
  77. webnotes.response["type"] = "csv"
  78. def to_csv(data):
  79. writer = UnicodeWriter()
  80. for row in data:
  81. writer.writerow(row)
  82. return writer.getvalue()
  83. class UnicodeWriter:
  84. def __init__(self, encoding="utf-8"):
  85. self.encoding = encoding
  86. self.queue = cStringIO.StringIO()
  87. self.writer = csv.writer(self.queue, quoting=csv.QUOTE_NONNUMERIC)
  88. def writerow(self, row):
  89. row = encode(row, self.encoding)
  90. self.writer.writerow(row)
  91. def getvalue(self):
  92. return self.queue.getvalue()
  93. def check_record(d, parenttype=None, doctype_dl=None):
  94. """check for mandatory, select options, dates. these should ideally be in doclist"""
  95. from webnotes.utils.dateutils import parse_date
  96. if parenttype and not d.get('parent'):
  97. webnotes.msgprint(_("Parent is required."), raise_exception=1)
  98. if not doctype_dl:
  99. doctype_dl = webnotes.model.doctype.get(d.doctype)
  100. for key in d:
  101. docfield = doctype_dl.get_field(key)
  102. val = d[key]
  103. if docfield:
  104. if docfield.reqd and (val=='' or val==None):
  105. webnotes.msgprint("%s is mandatory." % docfield.label, raise_exception=1)
  106. if docfield.fieldtype=='Select' and val and docfield.options:
  107. if docfield.options.startswith('link:'):
  108. link_doctype = docfield.options.split(':')[1]
  109. if not webnotes.conn.exists(link_doctype, val):
  110. webnotes.msgprint("%s must be a valid %s" % (docfield.label, link_doctype),
  111. raise_exception=1)
  112. elif docfield.options == "attach_files:":
  113. pass
  114. elif val not in docfield.options.split('\n'):
  115. webnotes.msgprint("%s must be one of: %s" % (docfield.label,
  116. ", ".join(filter(None, docfield.options.split("\n")))), raise_exception=1)
  117. if val and docfield.fieldtype=='Date':
  118. d[key] = parse_date(val)
  119. elif val and docfield.fieldtype in ["Int", "Check"]:
  120. d[key] = cint(val)
  121. elif val and docfield.fieldtype in ["Currency", "Float"]:
  122. d[key] = flt(val)
  123. def import_doc(d, doctype, overwrite, row_idx, submit=False):
  124. """import main (non child) document"""
  125. if webnotes.conn.exists(doctype, d['name']):
  126. if overwrite:
  127. bean = webnotes.bean(doctype, d['name'])
  128. bean.doc.fields.update(d)
  129. if d.get("docstatus") == 1:
  130. bean.update_after_submit()
  131. else:
  132. bean.save()
  133. return 'Updated row (#%d) %s' % (row_idx, getlink(doctype, d['name']))
  134. else:
  135. return 'Ignored row (#%d) %s (exists)' % (row_idx,
  136. getlink(doctype, d['name']))
  137. else:
  138. bean = webnotes.bean([d])
  139. bean.insert()
  140. if submit:
  141. bean.submit()
  142. return 'Inserted row (#%d) %s' % (row_idx, getlink(doctype,
  143. bean.doc.fields['name']))
  144. def getlink(doctype, name):
  145. return '<a href="#Form/%(doctype)s/%(name)s">%(name)s</a>' % locals()