Merge pull request #6166 from neilLasrado/demo
Merged Schools Demo into ERPNext
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index b28911e..3ebe873 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -344,7 +344,6 @@
against_acc.append(d.income_account)
self.against_income_account = ','.join(against_acc)
-
def add_remarks(self):
if not self.remarks: self.remarks = 'No Remarks'
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index ed429d6..e1f4f80 100644
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -53,9 +53,9 @@
self.filters["range3"] = "90"
for label in ("0-{range1}".format(range1=self.filters["range1"]),
- "{range1}-{range2}".format(range1=self.filters["range1"]+1, range2=self.filters["range2"]),
- "{range2}-{range3}".format(range2=self.filters["range2"]+1, range3=self.filters["range3"]),
- "{range3}-{above}".format(range3=self.filters["range3"] + 1, above=_("Above"))):
+ "{range1}-{range2}".format(range1=cint(self.filters["range1"])+ 1, range2=self.filters["range2"]),
+ "{range2}-{range3}".format(range2=cint(self.filters["range2"])+ 1, range3=self.filters["range3"]),
+ "{range3}-{above}".format(range3=cint(self.filters["range3"])+ 1, above=_("Above"))):
columns.append({
"label": label,
"fieldtype": "Currency",
diff --git a/erpnext/demo/data/course.json b/erpnext/demo/data/course.json
new file mode 100644
index 0000000..15728d5
--- /dev/null
+++ b/erpnext/demo/data/course.json
@@ -0,0 +1,134 @@
+[
+ {
+ "doctype": "Course",
+ "course_name": "Communication Skiils",
+ "course_code": "BCA2040",
+ "department": "Information Technology"
+ },
+ {
+ "doctype": "Course",
+ "course_name": "Object Oriented Programing - C++",
+ "course_code": "BCA2030",
+ "department": "Information Technology"
+ },
+ {
+ "doctype": "Course",
+ "course_name": "Data Structures and Algorithm",
+ "course_code": "BCA2020",
+ "department": "Information Technology"
+ },
+ {
+ "doctype": "Course",
+ "course_name": "Operating System",
+ "course_code": "BCA2010",
+ "department": "Information Technology"
+ },
+ {
+ "doctype": "Course",
+ "course_name": "Digital Logic",
+ "course_code": "BCA1040",
+ "department": "Information Technology"
+ },
+ {
+ "doctype": "Course",
+ "course_name": "Basic Mathematics",
+ "course_code": "BCA1030",
+ "department": "Information Technology"
+ },
+ {
+ "doctype": "Course",
+ "course_name": "Programing in C",
+ "course_code": "BCA1020",
+ "department": "Information Technology"
+ },
+ {
+ "doctype": "Course",
+ "course_name": "Fundamentals of IT & Programing",
+ "course_code": "BCA1010",
+ "department": "Information Technology"
+ },
+ {
+ "doctype": "Course",
+ "course_name": "Microprocessor",
+ "course_code": "MCA4010",
+ "department": "Information Technology"
+ },
+ {
+ "doctype": "Course",
+ "course_name": "Probability and Statistics",
+ "course_code": "MCA4020",
+ "department": "Information Technology"
+ },
+ {
+ "doctype": "Course",
+ "course_name": "Programing in Java",
+ "course_code": "MCA4030",
+ "department": "Information Technology"
+ },
+ {
+ "doctype": "Course",
+ "course_name": "Communication Skills",
+ "course_code": "BBA 101",
+ "department": "Management Studies"
+ },
+ {
+ "doctype": "Course",
+ "course_name": "Organizational Behavior",
+ "course_code": "BBA 102",
+ "department": "Management Studies"
+ },
+ {
+ "doctype": "Course",
+ "course_name": "Business Environment",
+ "course_code": "BBA 103",
+ "department": "Management Studies"
+ },
+ {
+ "doctype": "Course",
+ "course_name": "Legal and Regulatory Framework",
+ "course_code": "BBA 301",
+ "department": "Management Studies"
+ },
+ {
+ "doctype": "Course",
+ "course_name": "Human Resource Management",
+ "course_code": "BBA 302",
+ "department": "Management Studies"
+ },
+ {
+ "doctype": "Course",
+ "course_name": "Advertising and Sales",
+ "course_code": "BBA 304",
+ "department": "Management Studies"
+ },
+ {
+ "doctype": "Course",
+ "course_name": "Entrepreneurship Management",
+ "course_code": "BBA 505",
+ "department": "Management Studies"
+ },
+ {
+ "doctype": "Course",
+ "course_name": "Visual Merchandising",
+ "course_code": "BBR 504",
+ "department": "Management Studies"
+ },
+ {
+ "doctype": "Course",
+ "course_name": "Warehouse Management",
+ "course_code": "BBR 505",
+ "department": "Management Studies"
+ },
+ {
+ "doctype": "Course",
+ "course_name": "Store Operations and Job Knowledge",
+ "course_code": "BBR 501",
+ "department": "Management Studies"
+ },
+ {
+ "doctype": "Course",
+ "course_name": "Management Development and Skills",
+ "course_code": "BBA 602",
+ "department": "Management Studies"
+ }
+]
diff --git a/erpnext/demo/data/department.json b/erpnext/demo/data/department.json
new file mode 100644
index 0000000..f4355ba
--- /dev/null
+++ b/erpnext/demo/data/department.json
@@ -0,0 +1,30 @@
+[
+ {
+ "doctype": "Department",
+ "department_name": "Information Technology"
+ },
+ {
+ "doctype": "Department",
+ "department_name": "Physics"
+ },
+ {
+ "doctype": "Department",
+ "department_name": "Chemistry"
+ },
+ {
+ "doctype": "Department",
+ "department_name": "Biology"
+ },
+ {
+ "doctype": "Department",
+ "department_name": "Commerce"
+ },
+ {
+ "doctype": "Department",
+ "department_name": "English"
+ },
+ {
+ "doctype": "Department",
+ "department_name": "Management Studies"
+ }
+]
\ No newline at end of file
diff --git a/erpnext/demo/data/instructor.json b/erpnext/demo/data/instructor.json
new file mode 100644
index 0000000..a25d163
--- /dev/null
+++ b/erpnext/demo/data/instructor.json
@@ -0,0 +1,128 @@
+[
+ {
+ "doctype": "Instructor",
+ "instructor_name": "Eddie Jessup",
+ "naming_series": "INS/",
+ "department": "Information Technology"
+ },
+ {
+ "doctype": "Instructor",
+ "instructor_name": "William Dyer",
+ "naming_series": "INS/",
+ "department": "Information Technology"
+ },
+ {
+ "doctype": "Instructor",
+ "instructor_name": "Alastor Moody",
+ "naming_series": "INS/",
+ "department": "Information Technology"
+ },
+ {
+ "doctype": "Instructor",
+ "instructor_name": "Charles Xavier",
+ "naming_series": "INS/",
+ "department": "Information Technology"
+ },
+ {
+ "doctype": "Instructor",
+ "instructor_name": "Cuthbert Calculus",
+ "naming_series": "INS/",
+ "department": "Information Technology"
+ },
+ {
+ "doctype": "Instructor",
+ "instructor_name": "Reed Richards",
+ "naming_series": "INS/",
+ "department": "Information Technology"
+ },
+ {
+ "doctype": "Instructor",
+ "instructor_name": "Urban Chronotis",
+ "naming_series": "INS/",
+ "department": "Physics"
+ },
+ {
+ "doctype": "Instructor",
+ "instructor_name": "River Song",
+ "naming_series": "INS/",
+ "department": "Physics"
+ },
+ {
+ "doctype": "Instructor",
+ "instructor_name": "Yana",
+ "naming_series": "INS/",
+ "department": "Physics"
+ },
+ {
+ "doctype": "Instructor",
+ "instructor_name": "Neil Lasrado",
+ "naming_series": "INS/",
+ "department": "Information Technology"
+ },
+ {
+ "doctype": "Instructor",
+ "instructor_name": "Deepshi Garg",
+ "naming_series": "INS/",
+ "department": "Chemistry"
+ },
+ {
+ "doctype": "Instructor",
+ "instructor_name": "Shubham Saxena",
+ "naming_series": "INS/",
+ "department": "Physics"
+ },
+ {
+ "doctype": "Instructor",
+ "instructor_name": "Rushabh Mehta",
+ "naming_series": "INS/",
+ "department": "Information Technology"
+ },
+ {
+ "doctype": "Instructor",
+ "instructor_name": "Umari Syed",
+ "naming_series": "INS/",
+ "department": "Chemistry"
+ },
+ {
+ "doctype": "Instructor",
+ "instructor_name": "Aman Singh",
+ "naming_series": "INS/",
+ "department": "Physics"
+ },
+ {
+ "doctype": "Instructor",
+ "instructor_name": "Nabin",
+ "naming_series": "INS/",
+ "department": "Chemistry"
+ },
+ {
+ "doctype": "Instructor",
+ "instructor_name": "Kanchan Chauhan",
+ "naming_series": "INS/",
+ "department": "Information Technology"
+ },
+ {
+ "doctype": "Instructor",
+ "instructor_name": "Valmik Jangla",
+ "naming_series": "INS/",
+ "department": "Chemistry"
+ },
+ {
+ "doctype": "Instructor",
+ "instructor_name": "Amit Jain",
+ "naming_series": "INS/",
+ "department": "Physics"
+ },
+ {
+ "doctype": "Instructor",
+ "instructor_name": "Shreyas P",
+ "naming_series": "INS/",
+ "department": "Chemistry"
+ },
+ {
+ "doctype": "Instructor",
+ "instructor_name": "Rohit",
+ "naming_series": "INS/",
+ "department": "Information Technology"
+ }
+]
\ No newline at end of file
diff --git a/erpnext/demo/data/item_schools.json b/erpnext/demo/data/item_schools.json
new file mode 100644
index 0000000..5eb6082
--- /dev/null
+++ b/erpnext/demo/data/item_schools.json
@@ -0,0 +1,94 @@
+[
+ {
+ "default_supplier": "Asiatic Solutions",
+ "default_warehouse": "Stores",
+ "item_code": "Books",
+ "item_group": "Raw Material",
+ "item_name": "Books"
+ },
+ {
+ "default_supplier": "HomeBase",
+ "default_warehouse": "Stores",
+ "item_code": "Pencil",
+ "item_group": "Raw Material",
+ "item_name": "Pencil"
+ },
+ {
+ "default_supplier": "New World Realty",
+ "default_warehouse": "Stores",
+ "item_code": "Tables",
+ "item_group": "Raw Material",
+ "item_name": "Tables"
+ },
+ {
+ "default_supplier": "Eagle Hardware",
+ "default_warehouse": "Stores",
+ "item_code": "Chair",
+ "item_group": "Raw Material",
+ "item_name": "Chair"
+ },
+ {
+ "default_supplier": "Asiatic Solutions",
+ "default_warehouse": "Stores",
+ "item_code": "Black Board",
+ "item_group": "Sub Assemblies",
+ "item_name": "Black Board"
+ },
+ {
+ "default_supplier": "HomeBase",
+ "default_warehouse": "Stores",
+ "item_code": "Chalk",
+ "item_group": "Raw Material",
+ "item_name": "Chalk"
+ },
+ {
+ "default_supplier": "HomeBase",
+ "default_warehouse": "Stores",
+ "item_code": "Notepad",
+ "item_group": "Raw Material",
+ "item_name": "Notepad"
+ },
+ {
+ "default_supplier": "Ks Merchandise",
+ "default_warehouse": "Stores",
+ "item_code": "Uniform",
+ "item_group": "Raw Material",
+ "item_name": "Uniform"
+ },
+ {
+ "is_stock_item": 0,
+ "description": "Computer",
+ "item_code": "Computer",
+ "item_name": "Computer",
+ "item_group": "Products"
+ },
+ {
+ "is_stock_item": 0,
+ "description": "Mobile",
+ "item_code": "Mobile",
+ "item_name": "Mobile",
+ "item_group": "Products"
+ },
+ {
+ "is_stock_item": 0,
+ "description": "ERP",
+ "item_code": "ERP",
+ "item_name": "ERP",
+ "item_group": "All Item Groups"
+ },
+ {
+ "is_stock_item": 0,
+ "description": "Autocad",
+ "item_code": "Autocad",
+ "item_name": "Autocad",
+ "item_group": "All Item Groups"
+ },
+ {
+ "default_warehouse": "Stores",
+ "item_code": "Service",
+ "item_group": "Services",
+ "item_name": "Service",
+ "has_variants": 0,
+ "is_stock_item": 0
+ }
+]
\ No newline at end of file
diff --git a/erpnext/demo/data/program.json b/erpnext/demo/data/program.json
new file mode 100644
index 0000000..8638311
--- /dev/null
+++ b/erpnext/demo/data/program.json
@@ -0,0 +1,102 @@
+[
+ {
+ "doctype": "Program",
+ "program_name": "Masters of Computer Applications",
+ "program_code": "MCA",
+ "department": "Information Technology",
+ "courses": [
+ {
+ "course": "Microprocessor",
+ "academic_term": "Semester 1"
+ },
+ {
+ "course": "Probability and Statistics",
+ "academic_term": "Semester 1"
+ },
+ {
+ "course": "Programing in Java",
+ "academic_term": "Semester 2"
+ }
+ ]
+ },
+ {
+ "doctype": "Program",
+ "program_name": "Bachelor of Computer Applications",
+ "program_code": "BCA",
+ "department": "Information Technology",
+ "courses": [
+ {
+ "course": "Communication Skiils",
+ "academic_term": "Semester 3"
+ },
+ {
+ "course": "Object Oriented Programing - C++",
+ "academic_term": "Semester 3"
+ },
+ {
+ "course": "Basic Mathematics",
+ "academic_term": "Semester 2"
+ },
+ {
+ "course": "Data Structures and Algorithm",
+ "academic_term": "Semester 2"
+ },
+ {
+ "course": "Digital Logic",
+ "academic_term": "Semester 2"
+ },
+ {
+ "course": "Fundamentals of IT & Programing",
+ "academic_term": "Semester 1"
+ },
+ {
+ "course": "Operating System",
+ "academic_term": "Semester 1"
+ },
+ {
+ "course": "Programing in C",
+ "academic_term": "Semester 1"
+ }
+ ]
+ },
+ {
+ "doctype": "Program",
+ "program_name": "Bachelor of Business Administration",
+ "program_code": "BBA",
+ "department": "Management Studies",
+ "courses": [
+ {
+ "course": "Organizational Behavior",
+ "academic_term": "Semester 1"
+ },
+ {
+ "course": "Management Development and Skills",
+ "academic_term": "Semester 1"
+ },
+ {
+ "course": "Legal and Regulatory Framework",
+ "academic_term": "Semester 1"
+ },
+ {
+ "course": "Human Resource Management",
+ "academic_term": "Semester 2"
+ },
+ {
+ "course": "Entrepreneurship Management",
+ "academic_term": "Semester 2"
+ },
+ {
+ "course": "Communication Skills",
+ "academic_term": "Semester 2"
+ },
+ {
+ "course": "Business Environment",
+ "academic_term": "Semester 3"
+ },
+ {
+ "course": "Advertising and Sales",
+ "academic_term": "Semester 3"
+ }
+ ]
+ }
+]
\ No newline at end of file
diff --git a/erpnext/demo/data/random_student_data.json b/erpnext/demo/data/random_student_data.json
new file mode 100644
index 0000000..babcc71
--- /dev/null
+++ b/erpnext/demo/data/random_student_data.json
@@ -0,0 +1,1604 @@
+[
+{
+"first_name": "amanda",
+"last_name": "edwards",
+"image": "https://randomuser.me/api/portraits/women/55.jpg",
+"gender": "Female"
+},
+{
+"first_name": "abbie",
+"last_name": "johnston",
+"image": "https://randomuser.me/api/portraits/women/46.jpg",
+"gender": "Female"
+},
+{
+"first_name": "heather",
+"last_name": "nelson",
+"image": "https://randomuser.me/api/portraits/women/13.jpg",
+"gender": "Female"
+},
+{
+"first_name": "maxwell",
+"last_name": "gilbert",
+"image": "https://randomuser.me/api/portraits/men/56.jpg",
+"gender": "Male"
+},
+{
+"first_name": "molly",
+"last_name": "ramirez",
+"image": "https://randomuser.me/api/portraits/women/71.jpg",
+"gender": "Female"
+},
+{
+"first_name": "ian",
+"last_name": "barrett",
+"image": "https://randomuser.me/api/portraits/men/68.jpg",
+"gender": "Male"
+},
+{
+"first_name": "kim",
+"last_name": "hudson",
+"image": "https://randomuser.me/api/portraits/women/53.jpg",
+"gender": "Female"
+},
+{
+"first_name": "bruce",
+"last_name": "murray",
+"image": "https://randomuser.me/api/portraits/men/59.jpg",
+"gender": "Male"
+},
+{
+"first_name": "henry",
+"last_name": "powell",
+"image": "https://randomuser.me/api/portraits/men/88.jpg",
+"gender": "Male"
+},
+{
+"first_name": "chris",
+"last_name": "foster",
+"image": "https://randomuser.me/api/portraits/men/5.jpg",
+"gender": "Male"
+},
+{
+"first_name": "billy",
+"last_name": "kim",
+"image": "https://randomuser.me/api/portraits/men/91.jpg",
+"gender": "Male"
+},
+{
+"first_name": "samuel",
+"last_name": "harper",
+"image": "https://randomuser.me/api/portraits/men/56.jpg",
+"gender": "Male"
+},
+{
+"first_name": "jayden",
+"last_name": "kelly",
+"image": "https://randomuser.me/api/portraits/men/31.jpg",
+"gender": "Male"
+},
+{
+"first_name": "grace",
+"last_name": "berry",
+"image": "https://randomuser.me/api/portraits/women/69.jpg",
+"gender": "Female"
+},
+{
+"first_name": "ronnie",
+"last_name": "nelson",
+"image": "https://randomuser.me/api/portraits/men/83.jpg",
+"gender": "Male"
+},
+{
+"first_name": "harvey",
+"last_name": "harper",
+"image": "https://randomuser.me/api/portraits/men/68.jpg",
+"gender": "Male"
+},
+{
+"first_name": "maya",
+"last_name": "fernandez",
+"image": "https://randomuser.me/api/portraits/women/79.jpg",
+"gender": "Female"
+},
+{
+"first_name": "faith",
+"last_name": "lewis",
+"image": "https://randomuser.me/api/portraits/women/84.jpg",
+"gender": "Female"
+},
+{
+"first_name": "kirk",
+"last_name": "macrae",
+"image": "https://randomuser.me/api/portraits/men/13.jpg",
+"gender": "Male"
+},
+{
+"first_name": "tracy",
+"last_name": "holt",
+"image": "https://randomuser.me/api/portraits/women/18.jpg",
+"gender": "Female"
+},
+{
+"first_name": "mandy",
+"last_name": "dean",
+"image": "https://randomuser.me/api/portraits/women/0.jpg",
+"gender": "Female"
+},
+{
+"first_name": "sam",
+"last_name": "dunn",
+"image": "https://randomuser.me/api/portraits/women/12.jpg",
+"gender": "Female"
+},
+{
+"first_name": "zoe",
+"last_name": "fleming",
+"image": "https://randomuser.me/api/portraits/women/9.jpg",
+"gender": "Female"
+},
+{
+"first_name": "jeffrey",
+"last_name": "stewart",
+"image": "https://randomuser.me/api/portraits/men/56.jpg",
+"gender": "Male"
+},
+{
+"first_name": "dick",
+"last_name": "ryan",
+"image": "https://randomuser.me/api/portraits/men/63.jpg",
+"gender": "Male"
+},
+{
+"first_name": "carl",
+"last_name": "neal",
+"image": "https://randomuser.me/api/portraits/men/41.jpg",
+"gender": "Male"
+},
+{
+"first_name": "scarlett",
+"last_name": "ruiz",
+"image": "https://randomuser.me/api/portraits/women/24.jpg",
+"gender": "Female"
+},
+{
+"first_name": "rene",
+"last_name": "hughes",
+"image": "https://randomuser.me/api/portraits/men/3.jpg",
+"gender": "Male"
+},
+{
+"first_name": "greg",
+"last_name": "montgomery",
+"image": "https://randomuser.me/api/portraits/men/12.jpg",
+"gender": "Male"
+},
+{
+"first_name": "matt",
+"last_name": "lane",
+"image": "https://randomuser.me/api/portraits/men/85.jpg",
+"gender": "Male"
+},
+{
+"first_name": "eleanor",
+"last_name": "pearson",
+"image": "https://randomuser.me/api/portraits/women/61.jpg",
+"gender": "Female"
+},
+{
+"first_name": "theodore",
+"last_name": "burton",
+"image": "https://randomuser.me/api/portraits/men/81.jpg",
+"gender": "Male"
+},
+{
+"first_name": "jesus",
+"last_name": "hunt",
+"image": "https://randomuser.me/api/portraits/men/50.jpg",
+"gender": "Male"
+},
+{
+"first_name": "taylor",
+"last_name": "alvarez",
+"image": "https://randomuser.me/api/portraits/men/0.jpg",
+"gender": "Male"
+},
+{
+"first_name": "barbara",
+"last_name": "lucas",
+"image": "https://randomuser.me/api/portraits/women/21.jpg",
+"gender": "Female"
+},
+{
+"first_name": "nicky",
+"last_name": "simmons",
+"image": "https://randomuser.me/api/portraits/women/29.jpg",
+"gender": "Female"
+},
+{
+"first_name": "arthur",
+"last_name": "obrien",
+"image": "https://randomuser.me/api/portraits/men/11.jpg",
+"gender": "Male"
+},
+{
+"first_name": "donna",
+"last_name": "holmes",
+"image": "https://randomuser.me/api/portraits/women/33.jpg",
+"gender": "Female"
+},
+{
+"first_name": "mitchell",
+"last_name": "castro",
+"image": "https://randomuser.me/api/portraits/men/26.jpg",
+"gender": "Male"
+},
+{
+"first_name": "byron",
+"last_name": "marshall",
+"image": "https://randomuser.me/api/portraits/men/57.jpg",
+"gender": "Male"
+},
+{
+"first_name": "larry",
+"last_name": "king",
+"image": "https://randomuser.me/api/portraits/men/58.jpg",
+"gender": "Male"
+},
+{
+"first_name": "deborah",
+"last_name": "fuller",
+"image": "https://randomuser.me/api/portraits/women/50.jpg",
+"gender": "Female"
+},
+{
+"first_name": "eleanor",
+"last_name": "elliott",
+"image": "https://randomuser.me/api/portraits/women/80.jpg",
+"gender": "Female"
+},
+{
+"first_name": "derrick",
+"last_name": "shaw",
+"image": "https://randomuser.me/api/portraits/men/78.jpg",
+"gender": "Male"
+},
+{
+"first_name": "barbara",
+"last_name": "lynch",
+"image": "https://randomuser.me/api/portraits/women/15.jpg",
+"gender": "Female"
+},
+{
+"first_name": "elijah",
+"last_name": "allen",
+"image": "https://randomuser.me/api/portraits/men/43.jpg",
+"gender": "Male"
+},
+{
+"first_name": "nicholas",
+"last_name": "harper",
+"image": "https://randomuser.me/api/portraits/men/2.jpg",
+"gender": "Male"
+},
+{
+"first_name": "sofia",
+"last_name": "riley",
+"image": "https://randomuser.me/api/portraits/women/96.jpg",
+"gender": "Female"
+},
+{
+"first_name": "jar",
+"last_name": "hunt",
+"image": "https://randomuser.me/api/portraits/men/72.jpg",
+"gender": "Male"
+},
+{
+"first_name": "philip",
+"last_name": "rose",
+"image": "https://randomuser.me/api/portraits/men/16.jpg",
+"gender": "Male"
+},
+{
+"first_name": "ella",
+"last_name": "moore",
+"image": "https://randomuser.me/api/portraits/women/83.jpg",
+"gender": "Female"
+},
+{
+"first_name": "seth",
+"last_name": "tucker",
+"image": "https://randomuser.me/api/portraits/men/6.jpg",
+"gender": "Male"
+},
+{
+"first_name": "abby",
+"last_name": "gonzalez",
+"image": "https://randomuser.me/api/portraits/women/18.jpg",
+"gender": "Female"
+},
+{
+"first_name": "noah",
+"last_name": "williamson",
+"image": "https://randomuser.me/api/portraits/men/54.jpg",
+"gender": "Male"
+},
+{
+"first_name": "cathy",
+"last_name": "gray",
+"image": "https://randomuser.me/api/portraits/women/88.jpg",
+"gender": "Female"
+},
+{
+"first_name": "barb",
+"last_name": "snyder",
+"image": "https://randomuser.me/api/portraits/women/49.jpg",
+"gender": "Female"
+},
+{
+"first_name": "rosalyn",
+"last_name": "hale",
+"image": "https://randomuser.me/api/portraits/women/64.jpg",
+"gender": "Female"
+},
+{
+"first_name": "jessica",
+"last_name": "armstrong",
+"image": "https://randomuser.me/api/portraits/women/95.jpg",
+"gender": "Female"
+},
+{
+"first_name": "vicki",
+"last_name": "wheeler",
+"image": "https://randomuser.me/api/portraits/women/49.jpg",
+"gender": "Female"
+},
+{
+"first_name": "luke",
+"last_name": "fisher",
+"image": "https://randomuser.me/api/portraits/men/77.jpg",
+"gender": "Male"
+},
+{
+"first_name": "joey",
+"last_name": "wheeler",
+"image": "https://randomuser.me/api/portraits/men/50.jpg",
+"gender": "Male"
+},
+{
+"first_name": "victoria",
+"last_name": "jimenez",
+"image": "https://randomuser.me/api/portraits/women/25.jpg",
+"gender": "Female"
+},
+{
+"first_name": "daryl",
+"last_name": "patterson",
+"image": "https://randomuser.me/api/portraits/men/30.jpg",
+"gender": "Male"
+},
+{
+"first_name": "dwayne",
+"last_name": "jensen",
+"image": "https://randomuser.me/api/portraits/men/71.jpg",
+"gender": "Male"
+},
+{
+"first_name": "herbert",
+"last_name": "silva",
+"image": "https://randomuser.me/api/portraits/men/83.jpg",
+"gender": "Male"
+},
+{
+"first_name": "walter",
+"last_name": "walker",
+"image": "https://randomuser.me/api/portraits/men/91.jpg",
+"gender": "Male"
+},
+{
+"first_name": "logan",
+"last_name": "banks",
+"image": "https://randomuser.me/api/portraits/men/67.jpg",
+"gender": "Male"
+},
+{
+"first_name": "shawn",
+"last_name": "harvey",
+"image": "https://randomuser.me/api/portraits/men/87.jpg",
+"gender": "Male"
+},
+{
+"first_name": "lawrence",
+"last_name": "bradley",
+"image": "https://randomuser.me/api/portraits/men/40.jpg",
+"gender": "Male"
+},
+{
+"first_name": "jack",
+"last_name": "fleming",
+"image": "https://randomuser.me/api/portraits/men/37.jpg",
+"gender": "Male"
+},
+{
+"first_name": "jackson",
+"last_name": "boyd",
+"image": "https://randomuser.me/api/portraits/men/68.jpg",
+"gender": "Male"
+},
+{
+"first_name": "cecil",
+"last_name": "webb",
+"image": "https://randomuser.me/api/portraits/men/9.jpg",
+"gender": "Male"
+},
+{
+"first_name": "eliza",
+"last_name": "mills",
+"image": "https://randomuser.me/api/portraits/women/20.jpg",
+"gender": "Female"
+},
+{
+"first_name": "jenny",
+"last_name": "frazier",
+"image": "https://randomuser.me/api/portraits/women/61.jpg",
+"gender": "Female"
+},
+{
+"first_name": "kent",
+"last_name": "butler",
+"image": "https://randomuser.me/api/portraits/men/64.jpg",
+"gender": "Male"
+},
+{
+"first_name": "rose",
+"last_name": "perry",
+"image": "https://randomuser.me/api/portraits/women/74.jpg",
+"gender": "Female"
+},
+{
+"first_name": "jack",
+"last_name": "king",
+"image": "https://randomuser.me/api/portraits/men/60.jpg",
+"gender": "Male"
+},
+{
+"first_name": "elmer",
+"last_name": "williams",
+"image": "https://randomuser.me/api/portraits/men/26.jpg",
+"gender": "Male"
+},
+{
+"first_name": "vanessa",
+"last_name": "torres",
+"image": "https://randomuser.me/api/portraits/women/41.jpg",
+"gender": "Female"
+},
+{
+"first_name": "tyrone",
+"last_name": "coleman",
+"image": "https://randomuser.me/api/portraits/men/59.jpg",
+"gender": "Male"
+},
+{
+"first_name": "julie",
+"last_name": "bradley",
+"image": "https://randomuser.me/api/portraits/women/50.jpg",
+"gender": "Female"
+},
+{
+"first_name": "fernando",
+"last_name": "castro",
+"image": "https://randomuser.me/api/portraits/men/44.jpg",
+"gender": "Male"
+},
+{
+"first_name": "sara",
+"last_name": "craig",
+"image": "https://randomuser.me/api/portraits/women/8.jpg",
+"gender": "Female"
+},
+{
+"first_name": "steven",
+"last_name": "stone",
+"image": "https://randomuser.me/api/portraits/men/47.jpg",
+"gender": "Male"
+},
+{
+"first_name": "barb",
+"last_name": "rodriquez",
+"image": "https://randomuser.me/api/portraits/women/73.jpg",
+"gender": "Female"
+},
+{
+"first_name": "charlie",
+"last_name": "king",
+"image": "https://randomuser.me/api/portraits/men/79.jpg",
+"gender": "Male"
+},
+{
+"first_name": "jessica",
+"last_name": "davis",
+"image": "https://randomuser.me/api/portraits/women/26.jpg",
+"gender": "Female"
+},
+{
+"first_name": "lewis",
+"last_name": "watson",
+"image": "https://randomuser.me/api/portraits/men/56.jpg",
+"gender": "Male"
+},
+{
+"first_name": "charlotte",
+"last_name": "johnson",
+"image": "https://randomuser.me/api/portraits/women/46.jpg",
+"gender": "Female"
+},
+{
+"first_name": "danielle",
+"last_name": "bell",
+"image": "https://randomuser.me/api/portraits/women/54.jpg",
+"gender": "Female"
+},
+{
+"first_name": "kristin",
+"last_name": "dixon",
+"image": "https://randomuser.me/api/portraits/women/23.jpg",
+"gender": "Female"
+},
+{
+"first_name": "andrea",
+"last_name": "thompson",
+"image": "https://randomuser.me/api/portraits/women/54.jpg",
+"gender": "Female"
+},
+{
+"first_name": "ashley",
+"last_name": "andrews",
+"image": "https://randomuser.me/api/portraits/women/46.jpg",
+"gender": "Female"
+},
+{
+"first_name": "sharon",
+"last_name": "martinez",
+"image": "https://randomuser.me/api/portraits/women/6.jpg",
+"gender": "Female"
+},
+{
+"first_name": "tristan",
+"last_name": "cunningham",
+"image": "https://randomuser.me/api/portraits/men/62.jpg",
+"gender": "Male"
+},
+{
+"first_name": "carol",
+"last_name": "chavez",
+"image": "https://randomuser.me/api/portraits/women/85.jpg",
+"gender": "Female"
+},
+{
+"first_name": "lauren",
+"last_name": "hudson",
+"image": "https://randomuser.me/api/portraits/women/88.jpg",
+"gender": "Female"
+},
+{
+"first_name": "guy",
+"last_name": "robertson",
+"image": "https://randomuser.me/api/portraits/men/78.jpg",
+"gender": "Male"
+},
+{
+"first_name": "debra",
+"last_name": "long",
+"image": "https://randomuser.me/api/portraits/women/23.jpg",
+"gender": "Female"
+},
+{
+"first_name": "taylor",
+"last_name": "carpenter",
+"image": "https://randomuser.me/api/portraits/men/0.jpg",
+"gender": "Male"
+},
+{
+"first_name": "eetu",
+"last_name": "annala",
+"image": "https://randomuser.me/api/portraits/men/31.jpg",
+"gender": "Male"
+},
+{
+"first_name": "oliver",
+"last_name": "moilanen",
+"image": "https://randomuser.me/api/portraits/men/14.jpg",
+"gender": "Male"
+},
+{
+"first_name": "leo",
+"last_name": "maunu",
+"image": "https://randomuser.me/api/portraits/men/72.jpg",
+"gender": "Male"
+},
+{
+"first_name": "iiris",
+"last_name": "kalas",
+"image": "https://randomuser.me/api/portraits/women/49.jpg",
+"gender": "Female"
+},
+{
+"first_name": "aada",
+"last_name": "kinnunen",
+"image": "https://randomuser.me/api/portraits/women/64.jpg",
+"gender": "Female"
+},
+{
+"first_name": "topias",
+"last_name": "walli",
+"image": "https://randomuser.me/api/portraits/men/58.jpg",
+"gender": "Male"
+},
+{
+"first_name": "viivi",
+"last_name": "toivonen",
+"image": "https://randomuser.me/api/portraits/women/16.jpg",
+"gender": "Female"
+},
+{
+"first_name": "iina",
+"last_name": "makinen",
+"image": "https://randomuser.me/api/portraits/women/44.jpg",
+"gender": "Female"
+},
+{
+"first_name": "lumi",
+"last_name": "tuominen",
+"image": "https://randomuser.me/api/portraits/women/11.jpg",
+"gender": "Female"
+},
+{
+"first_name": "ellen",
+"last_name": "koski",
+"image": "https://randomuser.me/api/portraits/women/22.jpg",
+"gender": "Female"
+},
+{
+"first_name": "onni",
+"last_name": "laurila",
+"image": "https://randomuser.me/api/portraits/men/74.jpg",
+"gender": "Male"
+},
+{
+"first_name": "eevi",
+"last_name": "niskanen",
+"image": "https://randomuser.me/api/portraits/women/72.jpg",
+"gender": "Female"
+},
+{
+"first_name": "julius",
+"last_name": "maijala",
+"image": "https://randomuser.me/api/portraits/men/8.jpg",
+"gender": "Male"
+},
+{
+"first_name": "sofia",
+"last_name": "tuomi",
+"image": "https://randomuser.me/api/portraits/women/1.jpg",
+"gender": "Female"
+},
+{
+"first_name": "oliver",
+"last_name": "jarvela",
+"image": "https://randomuser.me/api/portraits/men/60.jpg",
+"gender": "Male"
+},
+{
+"first_name": "luukas",
+"last_name": "mikkola",
+"image": "https://randomuser.me/api/portraits/men/90.jpg",
+"gender": "Male"
+},
+{
+"first_name": "amanda",
+"last_name": "anttila",
+"image": "https://randomuser.me/api/portraits/women/65.jpg",
+"gender": "Female"
+},
+{
+"first_name": "ella",
+"last_name": "sakala",
+"image": "https://randomuser.me/api/portraits/women/79.jpg",
+"gender": "Female"
+},
+{
+"first_name": "siiri",
+"last_name": "kinnunen",
+"image": "https://randomuser.me/api/portraits/women/37.jpg",
+"gender": "Female"
+},
+{
+"first_name": "joona",
+"last_name": "korhonen",
+"image": "https://randomuser.me/api/portraits/men/87.jpg",
+"gender": "Male"
+},
+{
+"first_name": "topias",
+"last_name": "korpi",
+"image": "https://randomuser.me/api/portraits/men/75.jpg",
+"gender": "Male"
+},
+{
+"first_name": "mikael",
+"last_name": "remes",
+"image": "https://randomuser.me/api/portraits/men/89.jpg",
+"gender": "Male"
+},
+{
+"first_name": "veera",
+"last_name": "peltola",
+"image": "https://randomuser.me/api/portraits/women/69.jpg",
+"gender": "Female"
+},
+{
+"first_name": "emil",
+"last_name": "makela",
+"image": "https://randomuser.me/api/portraits/men/98.jpg",
+"gender": "Male"
+},
+{
+"first_name": "luukas",
+"last_name": "kujala",
+"image": "https://randomuser.me/api/portraits/men/83.jpg",
+"gender": "Male"
+},
+{
+"first_name": "eemil",
+"last_name": "honkala",
+"image": "https://randomuser.me/api/portraits/men/85.jpg",
+"gender": "Male"
+},
+{
+"first_name": "peetu",
+"last_name": "kalm",
+"image": "https://randomuser.me/api/portraits/men/17.jpg",
+"gender": "Male"
+},
+{
+"first_name": "eemeli",
+"last_name": "lehtonen",
+"image": "https://randomuser.me/api/portraits/men/55.jpg",
+"gender": "Male"
+},
+{
+"first_name": "viivi",
+"last_name": "koistinen",
+"image": "https://randomuser.me/api/portraits/women/53.jpg",
+"gender": "Female"
+},
+{
+"first_name": "elli",
+"last_name": "savela",
+"image": "https://randomuser.me/api/portraits/women/77.jpg",
+"gender": "Female"
+},
+{
+"first_name": "venla",
+"last_name": "walli",
+"image": "https://randomuser.me/api/portraits/women/52.jpg",
+"gender": "Female"
+},
+{
+"first_name": "amanda",
+"last_name": "wuollet",
+"image": "https://randomuser.me/api/portraits/women/11.jpg",
+"gender": "Female"
+},
+{
+"first_name": "valtteri",
+"last_name": "hokkanen",
+"image": "https://randomuser.me/api/portraits/men/30.jpg",
+"gender": "Male"
+},
+{
+"first_name": "veera",
+"last_name": "maki",
+"image": "https://randomuser.me/api/portraits/women/34.jpg",
+"gender": "Female"
+},
+{
+"first_name": "kerttu",
+"last_name": "maunu",
+"image": "https://randomuser.me/api/portraits/women/1.jpg",
+"gender": "Female"
+},
+{
+"first_name": "nella",
+"last_name": "hanka",
+"image": "https://randomuser.me/api/portraits/women/70.jpg",
+"gender": "Female"
+},
+{
+"first_name": "iiris",
+"last_name": "hakala",
+"image": "https://randomuser.me/api/portraits/women/33.jpg",
+"gender": "Female"
+},
+{
+"first_name": "viivi",
+"last_name": "ojala",
+"image": "https://randomuser.me/api/portraits/women/69.jpg",
+"gender": "Female"
+},
+{
+"first_name": "iina",
+"last_name": "peura",
+"image": "https://randomuser.me/api/portraits/women/22.jpg",
+"gender": "Female"
+},
+{
+"first_name": "samuel",
+"last_name": "mattila",
+"image": "https://randomuser.me/api/portraits/men/88.jpg",
+"gender": "Male"
+},
+{
+"first_name": "julius",
+"last_name": "kumpula",
+"image": "https://randomuser.me/api/portraits/men/26.jpg",
+"gender": "Male"
+},
+{
+"first_name": "nooa",
+"last_name": "haapala",
+"image": "https://randomuser.me/api/portraits/men/77.jpg",
+"gender": "Male"
+},
+{
+"first_name": "elias",
+"last_name": "leppo",
+"image": "https://randomuser.me/api/portraits/men/50.jpg",
+"gender": "Male"
+},
+{
+"first_name": "niklas",
+"last_name": "elo",
+"image": "https://randomuser.me/api/portraits/men/64.jpg",
+"gender": "Male"
+},
+{
+"first_name": "olivia",
+"last_name": "nurmi",
+"image": "https://randomuser.me/api/portraits/women/82.jpg",
+"gender": "Female"
+},
+{
+"first_name": "milja",
+"last_name": "lassila",
+"image": "https://randomuser.me/api/portraits/women/47.jpg",
+"gender": "Female"
+},
+{
+"first_name": "daniel",
+"last_name": "kalas",
+"image": "https://randomuser.me/api/portraits/men/53.jpg",
+"gender": "Male"
+},
+{
+"first_name": "enni",
+"last_name": "ramo",
+"image": "https://randomuser.me/api/portraits/women/18.jpg",
+"gender": "Female"
+},
+{
+"first_name": "matilda",
+"last_name": "salmi",
+"image": "https://randomuser.me/api/portraits/women/84.jpg",
+"gender": "Female"
+},
+{
+"first_name": "valtteri",
+"last_name": "wirta",
+"image": "https://randomuser.me/api/portraits/men/26.jpg",
+"gender": "Male"
+},
+{
+"first_name": "julius",
+"last_name": "maijala",
+"image": "https://randomuser.me/api/portraits/men/39.jpg",
+"gender": "Male"
+},
+{
+"first_name": "kerttu",
+"last_name": "peltola",
+"image": "https://randomuser.me/api/portraits/women/39.jpg",
+"gender": "Female"
+},
+{
+"first_name": "aada",
+"last_name": "kokko",
+"image": "https://randomuser.me/api/portraits/women/26.jpg",
+"gender": "Female"
+},
+{
+"first_name": "elsa",
+"last_name": "niska",
+"image": "https://randomuser.me/api/portraits/women/26.jpg",
+"gender": "Female"
+},
+{
+"first_name": "ella",
+"last_name": "kalm",
+"image": "https://randomuser.me/api/portraits/women/61.jpg",
+"gender": "Female"
+},
+{
+"first_name": "lilja",
+"last_name": "heinonen",
+"image": "https://randomuser.me/api/portraits/women/65.jpg",
+"gender": "Female"
+},
+{
+"first_name": "akseli",
+"last_name": "laakso",
+"image": "https://randomuser.me/api/portraits/men/64.jpg",
+"gender": "Male"
+},
+{
+"first_name": "lotta",
+"last_name": "saarela",
+"image": "https://randomuser.me/api/portraits/women/69.jpg",
+"gender": "Female"
+},
+{
+"first_name": "leo",
+"last_name": "polon",
+"image": "https://randomuser.me/api/portraits/men/5.jpg",
+"gender": "Male"
+},
+{
+"first_name": "aleksi",
+"last_name": "wuollet",
+"image": "https://randomuser.me/api/portraits/men/87.jpg",
+"gender": "Male"
+},
+{
+"first_name": "eemil",
+"last_name": "kalas",
+"image": "https://randomuser.me/api/portraits/men/6.jpg",
+"gender": "Male"
+},
+{
+"first_name": "emmi",
+"last_name": "koistinen",
+"image": "https://randomuser.me/api/portraits/women/66.jpg",
+"gender": "Female"
+},
+{
+"first_name": "väinö",
+"last_name": "halla",
+"image": "https://randomuser.me/api/portraits/men/65.jpg",
+"gender": "Male"
+},
+{
+"first_name": "eemil",
+"last_name": "heikkila",
+"image": "https://randomuser.me/api/portraits/men/18.jpg",
+"gender": "Male"
+},
+{
+"first_name": "amanda",
+"last_name": "lakso",
+"image": "https://randomuser.me/api/portraits/women/29.jpg",
+"gender": "Female"
+},
+{
+"first_name": "vilho",
+"last_name": "kivela",
+"image": "https://randomuser.me/api/portraits/men/19.jpg",
+"gender": "Male"
+},
+{
+"first_name": "peppi",
+"last_name": "lehtinen",
+"image": "https://randomuser.me/api/portraits/women/80.jpg",
+"gender": "Female"
+},
+{
+"first_name": "onni",
+"last_name": "lehtinen",
+"image": "https://randomuser.me/api/portraits/men/0.jpg",
+"gender": "Male"
+},
+{
+"first_name": "onni",
+"last_name": "ahonen",
+"image": "https://randomuser.me/api/portraits/men/49.jpg",
+"gender": "Male"
+},
+{
+"first_name": "venla",
+"last_name": "ranta",
+"image": "https://randomuser.me/api/portraits/women/0.jpg",
+"gender": "Female"
+},
+{
+"first_name": "ronja",
+"last_name": "korhonen",
+"image": "https://randomuser.me/api/portraits/women/69.jpg",
+"gender": "Female"
+},
+{
+"first_name": "emmi",
+"last_name": "niva",
+"image": "https://randomuser.me/api/portraits/women/65.jpg",
+"gender": "Female"
+},
+{
+"first_name": "oskari",
+"last_name": "leppanen",
+"image": "https://randomuser.me/api/portraits/men/43.jpg",
+"gender": "Male"
+},
+{
+"first_name": "arttu",
+"last_name": "heinonen",
+"image": "https://randomuser.me/api/portraits/men/94.jpg",
+"gender": "Male"
+},
+{
+"first_name": "toivo",
+"last_name": "makela",
+"image": "https://randomuser.me/api/portraits/men/23.jpg",
+"gender": "Male"
+},
+{
+"first_name": "otto",
+"last_name": "leino",
+"image": "https://randomuser.me/api/portraits/men/51.jpg",
+"gender": "Male"
+},
+{
+"first_name": "milla",
+"last_name": "kokko",
+"image": "https://randomuser.me/api/portraits/women/66.jpg",
+"gender": "Female"
+},
+{
+"first_name": "konsta",
+"last_name": "lehto",
+"image": "https://randomuser.me/api/portraits/men/29.jpg",
+"gender": "Male"
+},
+{
+"first_name": "eeli",
+"last_name": "heikkinen",
+"image": "https://randomuser.me/api/portraits/men/50.jpg",
+"gender": "Male"
+},
+{
+"first_name": "matilda",
+"last_name": "tanner",
+"image": "https://randomuser.me/api/portraits/women/2.jpg",
+"gender": "Female"
+},
+{
+"first_name": "elias",
+"last_name": "kivisto",
+"image": "https://randomuser.me/api/portraits/men/40.jpg",
+"gender": "Male"
+},
+{
+"first_name": "akseli",
+"last_name": "wirta",
+"image": "https://randomuser.me/api/portraits/men/90.jpg",
+"gender": "Male"
+},
+{
+"first_name": "leevi",
+"last_name": "kallio",
+"image": "https://randomuser.me/api/portraits/men/89.jpg",
+"gender": "Male"
+},
+{
+"first_name": "emilia",
+"last_name": "pelto",
+"image": "https://randomuser.me/api/portraits/women/0.jpg",
+"gender": "Female"
+},
+{
+"first_name": "niilo",
+"last_name": "keranen",
+"image": "https://randomuser.me/api/portraits/men/29.jpg",
+"gender": "Male"
+},
+{
+"first_name": "mikael",
+"last_name": "wainio",
+"image": "https://randomuser.me/api/portraits/men/85.jpg",
+"gender": "Male"
+},
+{
+"first_name": "elias",
+"last_name": "saksa",
+"image": "https://randomuser.me/api/portraits/men/53.jpg",
+"gender": "Male"
+},
+{
+"first_name": "aatu",
+"last_name": "erkkila",
+"image": "https://randomuser.me/api/portraits/men/6.jpg",
+"gender": "Male"
+},
+{
+"first_name": "arttu",
+"last_name": "jarvela",
+"image": "https://randomuser.me/api/portraits/men/49.jpg",
+"gender": "Male"
+},
+{
+"first_name": "matilda",
+"last_name": "lassila",
+"image": "https://randomuser.me/api/portraits/women/46.jpg",
+"gender": "Female"
+},
+{
+"first_name": "alisa",
+"last_name": "waara",
+"image": "https://randomuser.me/api/portraits/women/67.jpg",
+"gender": "Female"
+},
+{
+"first_name": "emilia",
+"last_name": "saksa",
+"image": "https://randomuser.me/api/portraits/women/66.jpg",
+"gender": "Female"
+},
+{
+"first_name": "valtteri",
+"last_name": "tikkanen",
+"image": "https://randomuser.me/api/portraits/men/88.jpg",
+"gender": "Male"
+},
+{
+"first_name": "konsta",
+"last_name": "rantala",
+"image": "https://randomuser.me/api/portraits/men/50.jpg",
+"gender": "Male"
+},
+{
+"first_name": "minttu",
+"last_name": "murto",
+"image": "https://randomuser.me/api/portraits/women/14.jpg",
+"gender": "Female"
+},
+{
+"first_name": "vilma",
+"last_name": "hatala",
+"image": "https://randomuser.me/api/portraits/women/60.jpg",
+"gender": "Female"
+},
+{
+"first_name": "anni",
+"last_name": "linna",
+"image": "https://randomuser.me/api/portraits/women/59.jpg",
+"gender": "Female"
+},
+{
+"first_name": "niklas",
+"last_name": "hautala",
+"image": "https://randomuser.me/api/portraits/men/7.jpg",
+"gender": "Male"
+},
+{
+"first_name": "niilo",
+"last_name": "lehtinen",
+"image": "https://randomuser.me/api/portraits/men/54.jpg",
+"gender": "Male"
+},
+{
+"first_name": "oona",
+"last_name": "saarinen",
+"image": "https://randomuser.me/api/portraits/women/71.jpg",
+"gender": "Female"
+},
+{
+"first_name": "constance",
+"last_name": "marie",
+"image": "https://randomuser.me/api/portraits/women/40.jpg",
+"gender": "Female"
+},
+{
+"first_name": "charles",
+"last_name": "pierre",
+"image": "https://randomuser.me/api/portraits/men/96.jpg",
+"gender": "Male"
+},
+{
+"first_name": "bérénice",
+"last_name": "leclerc",
+"image": "https://randomuser.me/api/portraits/women/39.jpg",
+"gender": "Female"
+},
+{
+"first_name": "clémence",
+"last_name": "arnaud",
+"image": "https://randomuser.me/api/portraits/women/48.jpg",
+"gender": "Female"
+},
+{
+"first_name": "melvin",
+"last_name": "lemoine",
+"image": "https://randomuser.me/api/portraits/men/47.jpg",
+"gender": "Male"
+},
+{
+"first_name": "marceau",
+"last_name": "joly",
+"image": "https://randomuser.me/api/portraits/men/56.jpg",
+"gender": "Male"
+},
+{
+"first_name": "garance",
+"last_name": "mathieu",
+"image": "https://randomuser.me/api/portraits/women/87.jpg",
+"gender": "Female"
+},
+{
+"first_name": "angèle",
+"last_name": "perrin",
+"image": "https://randomuser.me/api/portraits/women/88.jpg",
+"gender": "Female"
+},
+{
+"first_name": "pauline",
+"last_name": "simon",
+"image": "https://randomuser.me/api/portraits/women/82.jpg",
+"gender": "Female"
+},
+{
+"first_name": "apolline",
+"last_name": "laurent",
+"image": "https://randomuser.me/api/portraits/women/27.jpg",
+"gender": "Female"
+},
+{
+"first_name": "luca",
+"last_name": "lefevre",
+"image": "https://randomuser.me/api/portraits/men/40.jpg",
+"gender": "Male"
+},
+{
+"first_name": "bastien",
+"last_name": "roger",
+"image": "https://randomuser.me/api/portraits/men/73.jpg",
+"gender": "Male"
+},
+{
+"first_name": "marie",
+"last_name": "rodriguez",
+"image": "https://randomuser.me/api/portraits/women/18.jpg",
+"gender": "Female"
+},
+{
+"first_name": "tristan",
+"last_name": "renaud",
+"image": "https://randomuser.me/api/portraits/men/41.jpg",
+"gender": "Male"
+},
+{
+"first_name": "eva",
+"last_name": "philippe",
+"image": "https://randomuser.me/api/portraits/women/26.jpg",
+"gender": "Female"
+},
+{
+"first_name": "coline",
+"last_name": "dufour",
+"image": "https://randomuser.me/api/portraits/women/64.jpg",
+"gender": "Female"
+},
+{
+"first_name": "marilou",
+"last_name": "adam",
+"image": "https://randomuser.me/api/portraits/women/53.jpg",
+"gender": "Female"
+},
+{
+"first_name": "lia",
+"last_name": "renard",
+"image": "https://randomuser.me/api/portraits/women/88.jpg",
+"gender": "Female"
+},
+{
+"first_name": "timothee",
+"last_name": "rolland",
+"image": "https://randomuser.me/api/portraits/men/75.jpg",
+"gender": "Male"
+},
+{
+"first_name": "hélèna",
+"last_name": "boyer",
+"image": "https://randomuser.me/api/portraits/women/8.jpg",
+"gender": "Female"
+},
+{
+"first_name": "mélody",
+"last_name": "andre",
+"image": "https://randomuser.me/api/portraits/women/75.jpg",
+"gender": "Female"
+},
+{
+"first_name": "jeanne",
+"last_name": "duval",
+"image": "https://randomuser.me/api/portraits/women/44.jpg",
+"gender": "Female"
+},
+{
+"first_name": "elias",
+"last_name": "dupont",
+"image": "https://randomuser.me/api/portraits/men/60.jpg",
+"gender": "Male"
+},
+{
+"first_name": "estelle",
+"last_name": "bernard",
+"image": "https://randomuser.me/api/portraits/women/23.jpg",
+"gender": "Female"
+},
+{
+"first_name": "roxane",
+"last_name": "garnier",
+"image": "https://randomuser.me/api/portraits/women/14.jpg",
+"gender": "Female"
+},
+{
+"first_name": "maëva",
+"last_name": "guerin",
+"image": "https://randomuser.me/api/portraits/women/44.jpg",
+"gender": "Female"
+},
+{
+"first_name": "liam",
+"last_name": "carpentier",
+"image": "https://randomuser.me/api/portraits/men/41.jpg",
+"gender": "Male"
+},
+{
+"first_name": "théo",
+"last_name": "gaillard",
+"image": "https://randomuser.me/api/portraits/men/40.jpg",
+"gender": "Male"
+},
+{
+"first_name": "angelina",
+"last_name": "clement",
+"image": "https://randomuser.me/api/portraits/women/53.jpg",
+"gender": "Female"
+},
+{
+"first_name": "emma",
+"last_name": "bertrand",
+"image": "https://randomuser.me/api/portraits/women/86.jpg",
+"gender": "Female"
+},
+{
+"first_name": "charles",
+"last_name": "rolland",
+"image": "https://randomuser.me/api/portraits/men/14.jpg",
+"gender": "Male"
+},
+{
+"first_name": "nolan",
+"last_name": "gautier",
+"image": "https://randomuser.me/api/portraits/men/6.jpg",
+"gender": "Male"
+},
+{
+"first_name": "agathe",
+"last_name": "menard",
+"image": "https://randomuser.me/api/portraits/women/69.jpg",
+"gender": "Female"
+},
+{
+"first_name": "gaëtan",
+"last_name": "leclerc",
+"image": "https://randomuser.me/api/portraits/men/60.jpg",
+"gender": "Male"
+},
+{
+"first_name": "clarisse",
+"last_name": "lemaire",
+"image": "https://randomuser.me/api/portraits/women/21.jpg",
+"gender": "Female"
+},
+{
+"first_name": "samuel",
+"last_name": "garnier",
+"image": "https://randomuser.me/api/portraits/men/16.jpg",
+"gender": "Male"
+},
+{
+"first_name": "eden",
+"last_name": "fontai",
+"image": "https://randomuser.me/api/portraits/women/17.jpg",
+"gender": "Female"
+},
+{
+"first_name": "maëva",
+"last_name": "pierre",
+"image": "https://randomuser.me/api/portraits/women/19.jpg",
+"gender": "Female"
+},
+{
+"first_name": "thomas",
+"last_name": "barbier",
+"image": "https://randomuser.me/api/portraits/men/31.jpg",
+"gender": "Male"
+},
+{
+"first_name": "lily",
+"last_name": "lefebvre",
+"image": "https://randomuser.me/api/portraits/women/76.jpg",
+"gender": "Female"
+},
+{
+"first_name": "lise",
+"last_name": "perez",
+"image": "https://randomuser.me/api/portraits/women/74.jpg",
+"gender": "Female"
+},
+{
+"first_name": "mila",
+"last_name": "moulin",
+"image": "https://randomuser.me/api/portraits/women/43.jpg",
+"gender": "Female"
+},
+{
+"first_name": "dylan",
+"last_name": "picard",
+"image": "https://randomuser.me/api/portraits/men/37.jpg",
+"gender": "Male"
+},
+{
+"first_name": "amandine",
+"last_name": "rodriguez",
+"image": "https://randomuser.me/api/portraits/women/65.jpg",
+"gender": "Female"
+},
+{
+"first_name": "diego",
+"last_name": "girard",
+"image": "https://randomuser.me/api/portraits/men/84.jpg",
+"gender": "Male"
+},
+{
+"first_name": "elouan",
+"last_name": "garnier",
+"image": "https://randomuser.me/api/portraits/men/94.jpg",
+"gender": "Male"
+},
+{
+"first_name": "apolline",
+"last_name": "fleury",
+"image": "https://randomuser.me/api/portraits/women/65.jpg",
+"gender": "Female"
+},
+{
+"first_name": "coline",
+"last_name": "menard",
+"image": "https://randomuser.me/api/portraits/women/83.jpg",
+"gender": "Female"
+},
+{
+"first_name": "maëly",
+"last_name": "le gall",
+"image": "https://randomuser.me/api/portraits/women/60.jpg",
+"gender": "Female"
+},
+{
+"first_name": "justin",
+"last_name": "robert",
+"image": "https://randomuser.me/api/portraits/men/20.jpg",
+"gender": "Male"
+},
+{
+"first_name": "ryan",
+"last_name": "faure",
+"image": "https://randomuser.me/api/portraits/men/16.jpg",
+"gender": "Male"
+},
+{
+"first_name": "ninon",
+"last_name": "brunet",
+"image": "https://randomuser.me/api/portraits/women/68.jpg",
+"gender": "Female"
+},
+{
+"first_name": "tessa",
+"last_name": "garnier",
+"image": "https://randomuser.me/api/portraits/women/54.jpg",
+"gender": "Female"
+},
+{
+"first_name": "ryan",
+"last_name": "bonnet",
+"image": "https://randomuser.me/api/portraits/men/28.jpg",
+"gender": "Male"
+},
+{
+"first_name": "aurélien",
+"last_name": "andre",
+"image": "https://randomuser.me/api/portraits/men/29.jpg",
+"gender": "Male"
+},
+{
+"first_name": "clément",
+"last_name": "dumas",
+"image": "https://randomuser.me/api/portraits/men/10.jpg",
+"gender": "Male"
+},
+{
+"first_name": "alexis",
+"last_name": "fournier",
+"image": "https://randomuser.me/api/portraits/men/83.jpg",
+"gender": "Male"
+},
+{
+"first_name": "valentin",
+"last_name": "lecomte",
+"image": "https://randomuser.me/api/portraits/men/44.jpg",
+"gender": "Male"
+},
+{
+"first_name": "florian",
+"last_name": "olivier",
+"image": "https://randomuser.me/api/portraits/men/36.jpg",
+"gender": "Male"
+},
+{
+"first_name": "ewen",
+"last_name": "lefebvre",
+"image": "https://randomuser.me/api/portraits/men/32.jpg",
+"gender": "Male"
+},
+{
+"first_name": "titouan",
+"last_name": "charles",
+"image": "https://randomuser.me/api/portraits/men/59.jpg",
+"gender": "Male"
+},
+{
+"first_name": "lila",
+"last_name": "aubert",
+"image": "https://randomuser.me/api/portraits/women/6.jpg",
+"gender": "Female"
+},
+{
+"first_name": "charline",
+"last_name": "caron",
+"image": "https://randomuser.me/api/portraits/women/49.jpg",
+"gender": "Female"
+},
+{
+"first_name": "soren",
+"last_name": "le gall",
+"image": "https://randomuser.me/api/portraits/men/77.jpg",
+"gender": "Male"
+},
+{
+"first_name": "fanny",
+"last_name": "louis",
+"image": "https://randomuser.me/api/portraits/women/90.jpg",
+"gender": "Female"
+},
+{
+"first_name": "julie",
+"last_name": "adam",
+"image": "https://randomuser.me/api/portraits/women/34.jpg",
+"gender": "Female"
+},
+{
+"first_name": "louka",
+"last_name": "boyer",
+"image": "https://randomuser.me/api/portraits/men/98.jpg",
+"gender": "Male"
+}
+]
diff --git a/erpnext/demo/data/room.json b/erpnext/demo/data/room.json
new file mode 100644
index 0000000..82f0868
--- /dev/null
+++ b/erpnext/demo/data/room.json
@@ -0,0 +1,122 @@
+[
+ {
+ "doctype": "Room",
+ "room_name": "Lecture Hall 1",
+ "room_number": "101",
+ "seating_capacity": 80
+ },
+ {
+ "doctype": "Room",
+ "room_name": "Lecture Hall 2",
+ "room_number": "102",
+ "seating_capacity": 80
+ },
+ {
+ "doctype": "Room",
+ "room_name": "Lecture Hall 3",
+ "room_number": "103",
+ "seating_capacity": 80
+ },
+ {
+ "doctype": "Room",
+ "room_name": "Lecture Hall 4",
+ "room_number": "104",
+ "seating_capacity": 80
+ },
+ {
+ "doctype": "Room",
+ "room_name": "Lecture Hall 4",
+ "room_number": "104",
+ "seating_capacity": 80
+ },
+ {
+ "doctype": "Room",
+ "room_name": "Lecture Hall 5",
+ "room_number": "201",
+ "seating_capacity": 120
+ },
+ {
+ "doctype": "Room",
+ "room_name": "Lecture Hall 6",
+ "room_number": "202",
+ "seating_capacity": 120
+ },
+ {
+ "doctype": "Room",
+ "room_name": "Lecture Hall 7",
+ "room_number": "203",
+ "seating_capacity": 120
+ },
+ {
+ "doctype": "Room",
+ "room_name": "Computer Lab 1",
+ "room_number": "301",
+ "seating_capacity": 40
+ },
+ {
+ "doctype": "Room",
+ "room_name": "Computer Lab 2",
+ "room_number": "302",
+ "seating_capacity": 60
+ },
+ {
+ "doctype": "Room",
+ "room_name": "Seminar Hall 1",
+ "room_number": "303",
+ "seating_capacity": 240
+ },
+ {
+ "doctype": "Room",
+ "room_name": "Auditorium",
+ "room_number": "400",
+ "seating_capacity": 450
+ },
+ {
+ "doctype": "Room",
+ "room_name": "Exam hall 1",
+ "room_number": "560",
+ "seating_capacity": 70
+ },
+ {
+ "doctype": "Room",
+ "room_name": "Exam hall 2",
+ "room_number": "561",
+ "seating_capacity": 70
+ },
+ {
+ "doctype": "Room",
+ "room_name": "Exam hall 2",
+ "room_number": "562",
+ "seating_capacity": 70
+ },
+ {
+ "doctype": "Room",
+ "room_name": "Exam hall 3",
+ "room_number": "563",
+ "seating_capacity": 70
+ },
+ {
+ "doctype": "Room",
+ "room_name": "Exam hall 4",
+ "room_number": "564",
+ "seating_capacity": 70
+ },
+ {
+ "doctype": "Room",
+ "room_name": "Exam hall 5",
+ "room_number": "565",
+ "seating_capacity": 70
+ },
+ {
+ "doctype": "Room",
+ "room_name": "Exam hall 6",
+ "room_number": "566",
+ "seating_capacity": 70
+ },
+ {
+ "doctype": "Room",
+ "room_name": "Exam hall 7",
+ "room_number": "567",
+ "seating_capacity": 70
+ }
+]
\ No newline at end of file
diff --git a/erpnext/demo/data/user.json b/erpnext/demo/data/user.json
index e353efb..811e8af 100644
--- a/erpnext/demo/data/user.json
+++ b/erpnext/demo/data/user.json
@@ -26,8 +26,8 @@
},
{
"email": "aromn@example.com",
- "first_name": "\u0414\u043c\u0438\u0442\u0440\u0438\u0439",
- "last_name": "\u041f\u0438\u0440\u043e\u0433\u043e\u0432"
+ "first_name": "Arom",
+ "last_name": "Nolan"
},
{
"email": "TildeLindqvist@example.com",
diff --git a/erpnext/demo/demo.py b/erpnext/demo/demo.py
index d1f4982..180ddfa 100644
--- a/erpnext/demo/demo.py
+++ b/erpnext/demo/demo.py
@@ -3,9 +3,8 @@
import frappe, sys
import erpnext
import frappe.utils
-from erpnext.demo.setup_data import setup_data
-from erpnext.demo.user import hr, sales, purchase, manufacturing, stock, accounts, projects, fixed_asset
-
+from erpnext.demo.user import hr, sales, purchase, manufacturing, stock, accounts, projects, fixed_asset, schools
+from erpnext.demo.setup import education, manufacture, setup_data
"""
Make a demo
@@ -26,14 +25,19 @@
def make(domain='Manufacturing'):
frappe.flags.domain = domain
frappe.flags.mute_emails = True
- setup_data()
+ setup_data.setup(domain)
+ if domain== 'Manufacturing':
+ manufacture.setup_data()
+ elif domain== 'Education':
+ education.setup_data()
+
site = frappe.local.site
frappe.destroy()
frappe.init(site)
frappe.connect()
- simulate()
+ simulate(domain)
-def simulate():
+def simulate(domain='Manufacturing'):
runs_for = frappe.flags.runs_for or 150
frappe.flags.company = erpnext.get_default_company()
frappe.flags.mute_emails = True
@@ -47,33 +51,38 @@
# continue?
demo_last_date = frappe.db.get_global('demo_last_date')
if demo_last_date:
- current_date = frappe.utils.add_days(demo_last_date, 1)
-
+ current_date = frappe.utils.add_days(frappe.utils.getdate(demo_last_date), 1)
+
# run till today
if not runs_for:
runs_for = frappe.utils.date_diff(frappe.utils.nowdate(), current_date)
# runs_for = 100
fixed_asset.work()
-
for i in xrange(runs_for):
sys.stdout.write("\rSimulating {0}".format(current_date.strftime("%Y-%m-%d")))
sys.stdout.flush()
frappe.flags.current_date = current_date
-
if current_date.weekday() in (5, 6):
current_date = frappe.utils.add_days(current_date, 1)
continue
-
- hr.work()
- sales.work()
- purchase.work()
- manufacturing.work()
- stock.work()
- accounts.work()
- projects.run_projects(current_date)
- # run_messages()
-
- current_date = frappe.utils.add_days(current_date, 1)
-
- frappe.db.commit()
+ try:
+ hr.work()
+ purchase.work()
+ stock.work()
+ accounts.work()
+ projects.run_projects(current_date)
+ #run_messages()
+
+ if domain=='Manufacturing':
+ sales.work()
+ manufacturing.work()
+ elif domain=='Education':
+ schools.work()
+
+ except:
+ frappe.db.set_global('demo_last_date', current_date)
+ raise
+ finally:
+ current_date = frappe.utils.add_days(current_date, 1)
+ frappe.db.commit()
diff --git a/erpnext/demo/domains.py b/erpnext/demo/domains.py
index 0217f24..5743e27 100644
--- a/erpnext/demo/domains.py
+++ b/erpnext/demo/domains.py
@@ -12,5 +12,8 @@
},
'Services': {
'company_name': 'Acme Consulting'
+ },
+ 'Education': {
+ 'company_name': 'Whitmore College'
}
}
\ No newline at end of file
diff --git a/erpnext/demo/setup/__init__.py b/erpnext/demo/setup/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/demo/setup/__init__.py
diff --git a/erpnext/demo/setup/education.py b/erpnext/demo/setup/education.py
new file mode 100644
index 0000000..b164057
--- /dev/null
+++ b/erpnext/demo/setup/education.py
@@ -0,0 +1,140 @@
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+import frappe, json
+from frappe.utils.make_random import get_random
+from datetime import datetime
+from erpnext.demo.setup.setup_data import import_json
+import random
+
+def setup_data():
+ frappe.flags.mute_emails = True
+ make_masters()
+ setup_item()
+ make_student_applicants()
+ make_student_group()
+ make_fees_category()
+ make_fees_structure()
+ frappe.db.commit()
+ frappe.clear_cache()
+
+def make_masters():
+ import_json("Room")
+ import_json("Department")
+ import_json("Instructor")
+ import_json("Course")
+ import_json("Program")
+ frappe.db.commit()
+
+def setup_item():
+ items = json.loads(open(frappe.get_app_path('erpnext', 'demo', 'data', 'item_schools.json')).read())
+ for i in items:
+ item = frappe.new_doc('Item')
+ item.update(i)
+ item.min_order_qty = random.randint(10, 30)
+ item.default_warehouse = frappe.get_all('Warehouse', filters={'warehouse_name': item.default_warehouse}, limit=1)[0].name
+ item.insert()
+
+def make_student_applicants():
+ blood_group = ["A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-"]
+ male_names = []
+ female_names = []
+
+ file_path = get_json_path("Random Student Data")
+ with open(file_path, "r") as open_file:
+ random_student_data = json.loads(open_file.read())
+ count = 1
+
+ for d in random_student_data:
+ if d.get('gender') == "Male":
+ male_names.append(d.get('first_name').title())
+
+ if d.get('gender') == "Female":
+ female_names.append(d.get('first_name').title())
+
+ for idx, d in enumerate(random_student_data):
+ student_applicant = frappe.new_doc("Student Applicant")
+ student_applicant.first_name = d.get('first_name').title()
+ student_applicant.last_name = d.get('last_name').title()
+ student_applicant.image = d.get('image')
+ student_applicant.gender = d.get('gender')
+ student_applicant.program = get_random("Program")
+ student_applicant.blood_group = random.choice(blood_group)
+ year = random.randint(1990, 1998)
+ month = random.randint(1, 12)
+ day = random.randint(1, 28)
+ student_applicant.date_of_birth = datetime(year, month, day)
+ student_applicant.mother_name = random.choice(female_names) + " " + d.get('last_name').title()
+ student_applicant.father_name = random.choice(male_names) + " " + d.get('last_name').title()
+ if student_applicant.gender == "Male":
+ student_applicant.middle_name = random.choice(male_names)
+ else:
+ student_applicant.middle_name = random.choice(female_names)
+ student_applicant.student_email_id = d.get('first_name') + "_" + \
+ student_applicant.middle_name + "_" + d.get('last_name') + "@example.com"
+ if count <5:
+ student_applicant.insert()
+ frappe.db.commit()
+ else:
+ student_applicant.submit()
+ frappe.db.commit()
+ count+=1
+
+def make_student_group():
+ for d in frappe.db.get_list("Academic Term"):
+ sg_tool = frappe.new_doc("Student Group Creation Tool")
+ sg_tool.academic_year = "2016-17"
+ sg_tool.academic_term = d.name
+ sg_tool.courses = sg_tool.get_courses()
+ sg_tool.create_student_groups()
+ frappe.db.commit()
+
+def make_fees_category():
+ fee_type = ["Tuition Fee", "Hostel Fee", "Logistics Fee",
+ "Medical Fee", "Mess Fee", "Security Deposit"]
+
+ fee_desc = {"Tuition Fee" : "Curricular activities which includes books, notebooks and faculty charges" ,
+ "Hostel Fee" : "Stay of students in institute premises",
+ "Logistics Fee" : "Lodging boarding of the students" ,
+ "Medical Fee" : "Medical welfare of the students",
+ "Mess Fee" : "Food and beverages for your ward",
+ "Security Deposit" : "In case your child is found to have damaged institutes property"
+ }
+
+ for i in fee_type:
+ fee_category = frappe.new_doc("Fee Category")
+ fee_category.category_name = i
+ fee_category.description = fee_desc[i]
+ fee_category.insert()
+ frappe.db.commit()
+
+def make_fees_structure():
+ for d in frappe.db.get_list("Program"):
+ program = frappe.get_doc("Program", d.name)
+ for academic_term in ["Semester 1", "Semester 2", "Semester 3"]:
+ fee_structure = frappe.new_doc("Fee Structure")
+ fee_structure.program = d.name
+ fee_structure.academic_term = random.choice(frappe.db.get_list("Academic Term")).name
+ for j in range(1,4):
+ temp = {"fees_category": random.choice(frappe.db.get_list("Fee Category")).name , "amount" : random.randint(500,1000)}
+ fee_structure.append("components", temp)
+ fee_structure.insert()
+ program.append("fees", {"academic_term": academic_term, "fee_structure": fee_structure.name, "amount": fee_structure.total_amount})
+ program.save()
+ frappe.db.commit()
+
+def get_json_path(doctype):
+ return frappe.get_app_path('erpnext', 'demo', 'data', frappe.scrub(doctype) + '.json')
+
+def weighted_choice(weights):
+ totals = []
+ running_total = 0
+
+ for w in weights:
+ running_total += w
+ totals.append(running_total)
+
+ rnd = random.random() * running_total
+ for i, total in enumerate(totals):
+ if rnd < total:
+ return i
diff --git a/erpnext/demo/setup/manufacture.py b/erpnext/demo/setup/manufacture.py
new file mode 100644
index 0000000..8ac2039
--- /dev/null
+++ b/erpnext/demo/setup/manufacture.py
@@ -0,0 +1,131 @@
+from __future__ import unicode_literals
+
+import random, json
+import frappe
+from frappe.utils import nowdate, add_days
+from erpnext.demo.setup.setup_data import import_json
+
+def setup_data():
+ import_json("Asset Category")
+ setup_item()
+ setup_workstation()
+ setup_asset()
+ import_json('Operation')
+ setup_item_price()
+ show_item_groups_in_website()
+ import_json('BOM', submit=True)
+ frappe.db.commit()
+ frappe.clear_cache()
+
+def setup_workstation():
+ workstations = [u'Drilling Machine 1', u'Lathe 1', u'Assembly Station 1', u'Assembly Station 2', u'Packing and Testing Station']
+ for w in workstations:
+ frappe.get_doc({
+ "doctype": "Workstation",
+ "workstation_name": w,
+ "holiday_list": frappe.get_all("Holiday List")[0].name,
+ "hour_rate_consumable": int(random.random() * 20),
+ "hour_rate_electricity": int(random.random() * 10),
+ "hour_rate_labour": int(random.random() * 40),
+ "hour_rate_rent": int(random.random() * 10),
+ "working_hours": [
+ {
+ "enabled": 1,
+ "start_time": "8:00:00",
+ "end_time": "15:00:00"
+ }
+ ]
+ }).insert()
+
+def show_item_groups_in_website():
+ """set show_in_website=1 for Item Groups"""
+ products = frappe.get_doc("Item Group", "Products")
+ products.show_in_website = 1
+ products.route = 'products'
+ products.save()
+
+def setup_asset():
+ assets = json.loads(open(frappe.get_app_path('erpnext', 'demo', 'data', 'asset.json')).read())
+ for d in assets:
+ asset = frappe.new_doc('Asset')
+ asset.update(d)
+ asset.purchase_date = add_days(nowdate(), -random.randint(20, 1500))
+ asset.next_depreciation_date = add_days(asset.purchase_date, 30)
+ asset.warehouse = "Stores - WPL"
+ asset.set_missing_values()
+ asset.make_depreciation_schedule()
+ asset.flags.ignore_validate = True
+ asset.save()
+ asset.submit()
+
+def setup_item():
+ items = json.loads(open(frappe.get_app_path('erpnext', 'demo', 'data', 'item.json')).read())
+ for i in items:
+ item = frappe.new_doc('Item')
+ item.update(i)
+ item.default_warehouse = frappe.get_all('Warehouse', filters={'warehouse_name': item.default_warehouse}, limit=1)[0].name
+ item.insert()
+
+def setup_product_bundle():
+ frappe.get_doc({
+ 'doctype': 'Product Bundle',
+ 'new_item_code': 'Wind Mill A Series with Spare Bearing',
+ 'items': [
+ {'item_code': 'Wind Mill A Series', 'qty': 1},
+ {'item_code': 'Bearing Collar', 'qty': 1},
+ {'item_code': 'Bearing Assembly', 'qty': 1},
+ ]
+ }).insert()
+
+def setup_item_price():
+ frappe.db.sql("delete from `tabItem Price`")
+
+ standard_selling = {
+ "Base Bearing Plate": 28,
+ "Base Plate": 21,
+ "Bearing Assembly": 300,
+ "Bearing Block": 14,
+ "Bearing Collar": 103.6,
+ "Bearing Pipe": 63,
+ "Blade Rib": 46.2,
+ "Disc Collars": 42,
+ "External Disc": 56,
+ "Internal Disc": 70,
+ "Shaft": 340,
+ "Stand": 400,
+ "Upper Bearing Plate": 300,
+ "Wind Mill A Series": 320,
+ "Wind Mill A Series with Spare Bearing": 750,
+ "Wind MIll C Series": 400,
+ "Wind Turbine": 400,
+ "Wing Sheet": 30.8
+ }
+
+ standard_buying = {
+ "Base Bearing Plate": 20,
+ "Base Plate": 28,
+ "Base Plate Un Painted": 16,
+ "Bearing Block": 13,
+ "Bearing Collar": 96.4,
+ "Bearing Pipe": 55,
+ "Blade Rib": 38,
+ "Disc Collars": 34,
+ "External Disc": 50,
+ "Internal Disc": 60,
+ "Shaft": 250,
+ "Stand": 300,
+ "Upper Bearing Plate": 200,
+ "Wing Sheet": 25
+ }
+
+ for price_list in ("standard_buying", "standard_selling"):
+ for item, rate in locals().get(price_list).iteritems():
+ frappe.get_doc({
+ "doctype": "Item Price",
+ "price_list": price_list.replace("_", " ").title(),
+ "item_code": item,
+ "selling": 1 if price_list=="standard_selling" else 0,
+ "buying": 1 if price_list=="standard_buying" else 0,
+ "price_list_rate": rate,
+ "currency": "USD"
+ }).insert()
diff --git a/erpnext/demo/setup_data.py b/erpnext/demo/setup/setup_data.py
similarity index 73%
rename from erpnext/demo/setup_data.py
rename to erpnext/demo/setup/setup_data.py
index 97dc894..d279a64 100644
--- a/erpnext/demo/setup_data.py
+++ b/erpnext/demo/setup/setup_data.py
@@ -1,43 +1,35 @@
from __future__ import unicode_literals
import random, json
+import frappe, erpnext
+from frappe.utils import flt, now_datetime, cstr
from frappe.utils.make_random import add_random_children, get_random
from erpnext.demo.domains import data
-import frappe, erpnext
-from frappe.utils import flt, now_datetime, cstr, nowdate, add_days
from frappe import _
-def setup_data():
- domain = frappe.flags.domain
+def setup(domain):
complete_setup(domain)
setup_demo_page()
setup_fiscal_year()
setup_holiday_list()
- setup_customer()
- setup_supplier()
- import_json("Asset Category")
- setup_item()
- setup_warehouse()
- setup_asset()
- import_json('Address')
- import_json('Contact')
- setup_workstation()
- import_json('Operation')
- import_json('Lead')
- setup_item_price()
- show_item_groups_in_website()
- setup_currency_exchange()
- import_json('BOM', submit=True)
setup_user()
setup_employee()
setup_salary_structure()
setup_salary_structure_for_timesheet()
setup_leave_allocation()
+ setup_user_roles()
+ setup_customer()
+ setup_supplier()
+ setup_warehouse()
+ import_json('Address')
+ import_json('Contact')
+ import_json('Lead')
+ setup_currency_exchange()
setup_mode_of_payment()
setup_account_to_expense_type()
- setup_user_roles()
setup_budget()
setup_pos_profile()
+
frappe.db.commit()
frappe.clear_cache()
@@ -105,106 +97,6 @@
frappe.set_value("Company", erpnext.get_default_company(), "default_holiday_list", holiday_list.name)
-def setup_customer():
- customers = [u'Asian Junction', u'Life Plan Counselling', u'Two Pesos', u'Mr Fables', u'Intelacard', u'Big D Supermarkets', u'Adaptas', u'Nelson Brothers', u'Landskip Yard Care', u'Buttrey Food & Drug', u'Fayva', u'Asian Fusion', u'Crafts Canada', u'Consumers and Consumers Express', u'Netobill', u'Choices', u'Chi-Chis', u'Red Food', u'Endicott Shoes', u'Hind Enterprises']
- for c in customers:
- frappe.get_doc({
- "doctype": "Customer",
- "customer_name": c,
- "customer_group": "Commercial",
- "customer_type": random.choice(["Company", "Individual"]),
- "territory": "Rest Of The World"
- }).insert()
-
-def setup_supplier():
- suppliers = [u'Helios Air', u'Ks Merchandise', u'HomeBase', u'Scott Ties', u'Reliable Investments', u'Nan Duskin', u'Rainbow Records', u'New World Realty', u'Asiatic Solutions', u'Eagle Hardware', u'Modern Electricals']
- for s in suppliers:
- frappe.get_doc({
- "doctype": "Supplier",
- "supplier_name": s,
- "supplier_type": random.choice(["Services", "Raw Material"]),
- }).insert()
-
-def setup_workstation():
- workstations = [u'Drilling Machine 1', u'Lathe 1', u'Assembly Station 1', u'Assembly Station 2', u'Packing and Testing Station']
- for w in workstations:
- frappe.get_doc({
- "doctype": "Workstation",
- "workstation_name": w,
- "holiday_list": frappe.get_all("Holiday List")[0].name,
- "hour_rate_consumable": int(random.random() * 20),
- "hour_rate_electricity": int(random.random() * 10),
- "hour_rate_labour": int(random.random() * 40),
- "hour_rate_rent": int(random.random() * 10),
- "working_hours": [
- {
- "enabled": 1,
- "start_time": "8:00:00",
- "end_time": "15:00:00"
- }
- ]
- }).insert()
-
-def show_item_groups_in_website():
- """set show_in_website=1 for Item Groups"""
- products = frappe.get_doc("Item Group", "Products")
- products.show_in_website = 1
- products.route = 'products'
- products.save()
-
-def setup_item():
- items = json.loads(open(frappe.get_app_path('erpnext', 'demo', 'data', 'item.json')).read())
- for i in items:
- item = frappe.new_doc('Item')
- item.update(i)
- item.min_order_qty = random.randint(10, 30)
- item.default_warehouse = frappe.get_all('Warehouse', filters={'warehouse_name': item.default_warehouse}, limit=1)[0].name
- item.insert()
-
-def setup_warehouse():
- w = frappe.new_doc('Warehouse')
- w.warehouse_name = 'Supplier'
- w.insert()
-
-def setup_asset():
- assets = json.loads(open(frappe.get_app_path('erpnext', 'demo', 'data', 'asset.json')).read())
- for d in assets:
- asset = frappe.new_doc('Asset')
- asset.update(d)
- asset.purchase_date = add_days(nowdate(), -random.randint(20, 1500))
- asset.next_depreciation_date = add_days(asset.purchase_date, 30)
- asset.warehouse = "Stores - WPL"
- asset.set_missing_values()
- asset.make_depreciation_schedule()
- asset.flags.ignore_validate = True
- asset.save()
- asset.submit()
-
-def setup_currency_exchange():
- frappe.get_doc({
- 'doctype': 'Currency Exchange',
- 'from_currency': 'EUR',
- 'to_currency': 'USD',
- 'exchange_rate': 1.13
- }).insert()
-
- frappe.get_doc({
- 'doctype': 'Currency Exchange',
- 'from_currency': 'CNY',
- 'to_currency': 'USD',
- 'exchange_rate': 0.16
- }).insert()
-
-def setup_product_bundle():
- frappe.get_doc({
- 'doctype': 'Product Bundle',
- 'new_item_code': 'Wind Mill A Series with Spare Bearing',
- 'items': [
- {'item_code': 'Wind Mill A Series', 'qty': 1},
- {'item_code': 'Bearing Collar', 'qty': 1},
- {'item_code': 'Bearing Assembly', 'qty': 1},
- ]
- }).insert()
def setup_user():
frappe.db.sql('delete from tabUser where name not in ("Guest", "Administrator")')
@@ -215,78 +107,12 @@
user.new_password = 'demo'
user.insert()
-def import_json(doctype, submit=False, values=None):
- frappe.flags.in_import = True
- data = json.loads(open(frappe.get_app_path('erpnext', 'demo', 'data',
- frappe.scrub(doctype) + '.json')).read())
- for d in data:
- doc = frappe.new_doc(doctype)
- doc.update(d)
- doc.insert()
- if submit:
- doc.submit()
-
- frappe.db.commit()
-
def setup_employee():
frappe.db.set_value("HR Settings", None, "emp_created_by", "Naming Series")
frappe.db.commit()
import_json('Employee')
-def setup_item_price():
- frappe.db.sql("delete from `tabItem Price`")
-
- standard_selling = {
- "Base Bearing Plate": 28,
- "Base Plate": 21,
- "Bearing Assembly": 300,
- "Bearing Block": 14,
- "Bearing Collar": 103.6,
- "Bearing Pipe": 63,
- "Blade Rib": 46.2,
- "Disc Collars": 42,
- "External Disc": 56,
- "Internal Disc": 70,
- "Shaft": 340,
- "Stand": 400,
- "Upper Bearing Plate": 300,
- "Wind Mill A Series": 320,
- "Wind Mill A Series with Spare Bearing": 750,
- "Wind MIll C Series": 400,
- "Wind Turbine": 400,
- "Wing Sheet": 30.8
- }
-
- standard_buying = {
- "Base Bearing Plate": 20,
- "Base Plate": 28,
- "Base Plate Un Painted": 16,
- "Bearing Block": 13,
- "Bearing Collar": 96.4,
- "Bearing Pipe": 55,
- "Blade Rib": 38,
- "Disc Collars": 34,
- "External Disc": 50,
- "Internal Disc": 60,
- "Shaft": 250,
- "Stand": 300,
- "Upper Bearing Plate": 200,
- "Wing Sheet": 25
- }
-
- for price_list in ("standard_buying", "standard_selling"):
- for item, rate in locals().get(price_list).iteritems():
- frappe.get_doc({
- "doctype": "Item Price",
- "price_list": price_list.replace("_", " ").title(),
- "item_code": item,
- "selling": 1 if price_list=="standard_selling" else 0,
- "buying": 1 if price_list=="standard_buying" else 0,
- "price_list_rate": rate,
- "currency": "USD"
- }).insert()
-
def setup_salary_structure():
f = frappe.get_doc('Fiscal Year', frappe.defaults.get_global_default('fiscal_year'))
@@ -331,69 +157,12 @@
ss_doc.hour_rate = flt(random.random() * 10, 2)
ss_doc.save(ignore_permissions=True)
-def setup_mode_of_payment():
- account_dict = {'Cash': 'Cash - WPL', 'Bank': 'National Bank - WPL'}
- for payment_mode in frappe.get_all('Mode of Payment', fields = ["name", "type"]):
- if payment_mode.type:
- mop = frappe.get_doc('Mode of Payment', payment_mode.name)
- mop.append('accounts', {
- 'company': erpnext.get_default_company(),
- 'default_account': account_dict.get(payment_mode.type)
- })
-
- mop.save(ignore_permissions=True)
-
-def setup_account():
- frappe.flags.in_import = True
- data = json.loads(open(frappe.get_app_path('erpnext', 'demo', 'data',
- 'account.json')).read())
- for d in data:
- doc = frappe.new_doc('Account')
- doc.update(d)
- doc.parent_account = frappe.db.get_value('Account', {'account_name': doc.parent_account})
- doc.insert()
-
-def setup_account_to_expense_type():
- expense_types = [{'name': _('Calls'), "account": "Sales Expenses - WPL"},
- {'name': _('Food'), "account": "Entertainment Expenses - WPL"},
- {'name': _('Medical'), "account": "Utility Expenses - WPL"},
- {'name': _('Others'), "account": "Miscellaneous Expenses - WPL"},
- {'name': _('Travel'), "account": "Travel Expenses - WPL"}]
-
- for expense_type in expense_types:
- doc = frappe.get_doc("Expense Claim Type", expense_type["name"])
- doc.append("accounts", {
- "company" : erpnext.get_default_company(),
- "default_account" : expense_type["account"]
- })
- doc.save(ignore_permissions=True)
-
-def setup_budget():
- fiscal_years = frappe.get_all("Fiscal Year", order_by="year_start_date")[-2:]
-
- for fy in fiscal_years:
- budget = frappe.new_doc("Budget")
- budget.cost_center = get_random("Cost Center")
- budget.fiscal_year = fy.name
- budget.action_if_annual_budget_exceeded = "Warn"
- expense_ledger_count = frappe.db.count("Account", {"is_group": "0", "root_type": "Expense"})
-
- add_random_children(budget, "accounts", rows=random.randint(10, expense_ledger_count), randomize = { "account": ("Account", {"is_group": "0", "root_type": "Expense"})
- }, unique="account")
-
- for d in budget.accounts:
- d.budget_amount = random.randint(5, 100) * 10000
-
- budget.save()
- budget.submit()
-
-
def setup_user_roles():
user = frappe.get_doc('User', 'demo@erpnext.com')
user.add_roles('HR User', 'HR Manager', 'Accounts User', 'Accounts Manager',
'Stock User', 'Stock Manager', 'Sales User', 'Sales Manager', 'Purchase User',
'Purchase Manager', 'Projects User', 'Manufacturing User', 'Manufacturing Manager',
- 'Support Team')
+ 'Support Team', 'Academics User')
if not frappe.db.get_global('demo_hr_user'):
user = frappe.get_doc('User', 'CharmaineGaudreau@example.com')
@@ -435,21 +204,15 @@
user.add_roles('HR User', 'Projects User')
frappe.db.set_global('demo_projects_user', user.name)
-def setup_pos_profile():
- pos = frappe.new_doc('POS Profile')
- pos.user = frappe.db.get_global('demo_accounts_user')
- pos.naming_series = 'SINV-'
- pos.update_stock = 0
- pos.write_off_account = 'Cost of Goods Sold - WPL'
- pos.write_off_cost_center = 'Main - WPL'
-
- pos.append('payments', {
- 'mode_of_payment': frappe.db.get_value('Mode of Payment', {'type': 'Cash'}, 'name'),
- 'amount': 0.0
- })
-
- pos.insert()
-
+ if not frappe.db.get_global('demo_schools_user'):
+ user = frappe.get_doc('User', 'aromn@example.com')
+ user.add_roles('Academics User')
+ frappe.db.set_global('demo_schools_user', user.name)
+
+ #Add Expense Approver
+ user = frappe.get_doc('User', 'WanMai@example.com')
+ user.add_roles('Expense Approver')
+
def setup_leave_allocation():
year = now_datetime().year
for employee in frappe.get_all('Employee', fields=['name']):
@@ -469,3 +232,131 @@
leave_allocation.insert()
leave_allocation.submit()
frappe.db.commit()
+
+def setup_customer():
+ customers = [u'Asian Junction', u'Life Plan Counselling', u'Two Pesos', u'Mr Fables', u'Intelacard', u'Big D Supermarkets', u'Adaptas', u'Nelson Brothers', u'Landskip Yard Care', u'Buttrey Food & Drug', u'Fayva', u'Asian Fusion', u'Crafts Canada', u'Consumers and Consumers Express', u'Netobill', u'Choices', u'Chi-Chis', u'Red Food', u'Endicott Shoes', u'Hind Enterprises']
+ for c in customers:
+ frappe.get_doc({
+ "doctype": "Customer",
+ "customer_name": c,
+ "customer_group": "Commercial",
+ "customer_type": random.choice(["Company", "Individual"]),
+ "territory": "Rest Of The World"
+ }).insert()
+
+def setup_supplier():
+ suppliers = [u'Helios Air', u'Ks Merchandise', u'HomeBase', u'Scott Ties', u'Reliable Investments', u'Nan Duskin', u'Rainbow Records', u'New World Realty', u'Asiatic Solutions', u'Eagle Hardware', u'Modern Electricals']
+ for s in suppliers:
+ frappe.get_doc({
+ "doctype": "Supplier",
+ "supplier_name": s,
+ "supplier_type": random.choice(["Services", "Raw Material"]),
+ }).insert()
+
+def setup_warehouse():
+ w = frappe.new_doc('Warehouse')
+ w.warehouse_name = 'Supplier'
+ w.insert()
+
+def setup_currency_exchange():
+ frappe.get_doc({
+ 'doctype': 'Currency Exchange',
+ 'from_currency': 'EUR',
+ 'to_currency': 'USD',
+ 'exchange_rate': 1.13
+ }).insert()
+
+ frappe.get_doc({
+ 'doctype': 'Currency Exchange',
+ 'from_currency': 'CNY',
+ 'to_currency': 'USD',
+ 'exchange_rate': 0.16
+ }).insert()
+
+def setup_mode_of_payment():
+ company_abbr = frappe.db.get_value("Company", erpnext.get_default_company(), "abbr")
+ account_dict = {'Cash': 'Cash - '+ company_abbr , 'Bank': 'National Bank - '+ company_abbr}
+ for payment_mode in frappe.get_all('Mode of Payment', fields = ["name", "type"]):
+ if payment_mode.type:
+ mop = frappe.get_doc('Mode of Payment', payment_mode.name)
+ mop.append('accounts', {
+ 'company': erpnext.get_default_company(),
+ 'default_account': account_dict.get(payment_mode.type)
+ })
+ mop.save(ignore_permissions=True)
+
+def setup_account():
+ frappe.flags.in_import = True
+ data = json.loads(open(frappe.get_app_path('erpnext', 'demo', 'data',
+ 'account.json')).read())
+ for d in data:
+ doc = frappe.new_doc('Account')
+ doc.update(d)
+ doc.parent_account = frappe.db.get_value('Account', {'account_name': doc.parent_account})
+ doc.insert()
+
+def setup_account_to_expense_type():
+ company_abbr = frappe.db.get_value("Company", erpnext.get_default_company(), "abbr")
+ expense_types = [{'name': _('Calls'), "account": "Sales Expenses - "+ company_abbr},
+ {'name': _('Food'), "account": "Entertainment Expenses - "+ company_abbr},
+ {'name': _('Medical'), "account": "Utility Expenses - "+ company_abbr},
+ {'name': _('Others'), "account": "Miscellaneous Expenses - "+ company_abbr},
+ {'name': _('Travel'), "account": "Travel Expenses - "+ company_abbr}]
+
+ for expense_type in expense_types:
+ doc = frappe.get_doc("Expense Claim Type", expense_type["name"])
+ doc.append("accounts", {
+ "company" : erpnext.get_default_company(),
+ "default_account" : expense_type["account"]
+ })
+ doc.save(ignore_permissions=True)
+
+def setup_budget():
+ fiscal_years = frappe.get_all("Fiscal Year", order_by="year_start_date")[-2:]
+
+ for fy in fiscal_years:
+ budget = frappe.new_doc("Budget")
+ budget.cost_center = get_random("Cost Center")
+ budget.fiscal_year = fy.name
+ budget.action_if_annual_budget_exceeded = "Warn"
+ expense_ledger_count = frappe.db.count("Account", {"is_group": "0", "root_type": "Expense"})
+
+ add_random_children(budget, "accounts", rows=random.randint(10, expense_ledger_count), randomize = { "account": ("Account", {"is_group": "0", "root_type": "Expense"})
+ }, unique="account")
+
+ for d in budget.accounts:
+ d.budget_amount = random.randint(5, 100) * 10000
+
+ budget.save()
+ budget.submit()
+
+def setup_pos_profile():
+ company_abbr = frappe.db.get_value("Company", erpnext.get_default_company(), "abbr")
+ pos = frappe.new_doc('POS Profile')
+ pos.user = frappe.db.get_global('demo_accounts_user')
+ pos.naming_series = 'SINV-'
+ pos.update_stock = 0
+ pos.write_off_account = 'Cost of Goods Sold - '+ company_abbr
+ pos.write_off_cost_center = 'Main - '+ company_abbr
+
+ pos.append('payments', {
+ 'mode_of_payment': frappe.db.get_value('Mode of Payment', {'type': 'Cash'}, 'name'),
+ 'amount': 0.0
+ })
+
+ pos.insert()
+
+def import_json(doctype, submit=False, values=None):
+ frappe.flags.in_import = True
+ data = json.loads(open(frappe.get_app_path('erpnext', 'demo', 'data',
+ frappe.scrub(doctype) + '.json')).read())
+ for d in data:
+ doc = frappe.new_doc(doctype)
+ doc.update(d)
+ doc.insert()
+ if submit:
+ doc.submit()
+
+ frappe.db.commit()
+
+
diff --git a/erpnext/demo/user/accounts.py b/erpnext/demo/user/accounts.py
index 045c306..392d13d 100644
--- a/erpnext/demo/user/accounts.py
+++ b/erpnext/demo/user/accounts.py
@@ -67,7 +67,7 @@
def make_payment_entries(ref_doctype, report):
outstanding_invoices = list(set([r[3] for r in query_report.run(report,
{"report_date": frappe.flags.current_date })["result"] if r[2]==ref_doctype]))
-
+
# make Payment Entry
for inv in outstanding_invoices[:random.randint(1, 2)]:
pe = get_payment_entry(ref_doctype, inv)
diff --git a/erpnext/demo/user/hr.py b/erpnext/demo/user/hr.py
index 73f330d..2b80afb 100644
--- a/erpnext/demo/user/hr.py
+++ b/erpnext/demo/user/hr.py
@@ -1,25 +1,28 @@
from __future__ import unicode_literals
import frappe
import random
-from frappe.utils import random_string, add_days
+from frappe.utils import random_string, add_days, cint
from erpnext.projects.doctype.timesheet.test_timesheet import make_timesheet
from erpnext.projects.doctype.timesheet.timesheet import make_salary_slip, make_sales_invoice
-from frappe.utils.make_random import how_many, get_random
+from frappe.utils.make_random import get_random
from erpnext.hr.doctype.expense_claim.expense_claim import get_expense_approver, make_bank_entry
from erpnext.hr.doctype.leave_application.leave_application import get_leave_balance_on, OverlapError
def work():
frappe.set_user(frappe.db.get_global('demo_hr_user'))
year, month = frappe.flags.current_date.strftime("%Y-%m").split("-")
+ prev_month = str(cint(month)- 1).zfill(2)
+ if month=="01":
+ prev_month = "12"
mark_attendance()
make_leave_application()
# process payroll
- if not frappe.db.get_value("Salary Slip", {"month": month, "fiscal_year": year}):
+ if not frappe.db.get_value("Salary Slip", {"month": prev_month, "fiscal_year": year}):
process_payroll = frappe.get_doc("Process Payroll", "Process Payroll")
process_payroll.company = frappe.flags.company
- process_payroll.month = month
+ process_payroll.month = prev_month
process_payroll.fiscal_year = year
process_payroll.create_sal_slip()
process_payroll.submit_salary_slip()
@@ -180,7 +183,7 @@
if leave:
attendance.status = "Absent"
else:
- attendance.status = "Present"
+ attendance.status = "Present"
attendance.save()
attendance.submit()
- frappe.db.commit()
\ No newline at end of file
+ frappe.db.commit()
diff --git a/erpnext/demo/user/projects.py b/erpnext/demo/user/projects.py
index e7febd0..505ccfd 100644
--- a/erpnext/demo/user/projects.py
+++ b/erpnext/demo/user/projects.py
@@ -5,8 +5,7 @@
import frappe
from frappe.utils import flt
-from frappe.utils.make_random import can_make
-from frappe.utils.make_random import how_many, get_random
+from frappe.utils.make_random import get_random
from erpnext.projects.doctype.timesheet.test_timesheet import make_timesheet
from erpnext.demo.user.hr import make_sales_invoice_for_timesheet
@@ -20,13 +19,12 @@
def make_timesheet_for_projects(current_date ):
for data in frappe.get_all("Task", ["name", "project"], {"status": "Open", "exp_end_date": ("<", current_date)}):
employee = get_random("Employee")
- if frappe.db.get_value('Salary Structure', {'employee': employee}, 'salary_slip_based_on_timesheet'):
- ts = make_timesheet(employee, simulate = True, billable = 1,
- activity_type=get_random("Activity Type"), project=data.project, task =data.name)
+ ts = make_timesheet(employee, simulate = True, billable = 1,
+ activity_type=get_random("Activity Type"), project=data.project, task =data.name)
- if flt(ts.total_billing_amount) > 0.0:
- make_sales_invoice_for_timesheet(ts.name)
- frappe.db.commit()
+ if flt(ts.total_billing_amount) > 0.0:
+ make_sales_invoice_for_timesheet(ts.name)
+ frappe.db.commit()
def close_tasks(current_date):
for task in frappe.get_all("Task", ["name"], {"status": "Open", "exp_end_date": ("<", current_date)}):
diff --git a/erpnext/demo/user/purchase.py b/erpnext/demo/user/purchase.py
index 6f06f26..ab8ec77 100644
--- a/erpnext/demo/user/purchase.py
+++ b/erpnext/demo/user/purchase.py
@@ -27,7 +27,6 @@
for mr in frappe.get_all('Material Request',
filters={'material_request_type': 'Purchase', 'status': 'Open'},
limit=random.randint(1,6)):
- print mr.name
if not frappe.get_all('Request for Quotation',
filters={'material_request': mr.name}, limit=1):
rfq = make_request_for_quotation(mr.name)
@@ -104,14 +103,12 @@
mr.material_request_type = "Purchase"
mr.transaction_date = frappe.flags.current_date
-
- moq = frappe.db.get_value('Item', item_code, 'min_order_qty')
-
+
mr.append("items", {
"doctype": "Material Request Item",
"schedule_date": frappe.utils.add_days(mr.transaction_date, 7),
"item_code": item_code,
- "qty": qty if qty > moq else moq
+ "qty": qty
})
mr.insert()
mr.submit()
@@ -125,33 +122,33 @@
def make_subcontract():
from erpnext.buying.doctype.purchase_order.purchase_order import make_stock_entry
-
- # make sub-contract PO
- po = frappe.new_doc("Purchase Order")
- po.is_subcontracted = "Yes"
- po.supplier = get_random("Supplier")
-
item_code = get_random("Item", {"is_sub_contracted_item": 1})
- moq = frappe.db.get_value('Item', item_code, 'min_order_qty')
+ if item_code:
+ # make sub-contract PO
+ po = frappe.new_doc("Purchase Order")
+ po.is_subcontracted = "Yes"
+ po.supplier = get_random("Supplier")
- po.append("items", {
- "item_code": item_code,
- "schedule_date": frappe.utils.add_days(frappe.flags.current_date, 7),
- "qty": moq
- })
- po.set_missing_values()
- try:
- po.insert()
- except InvalidCurrency:
- return
+ item_code = get_random("Item", {"is_sub_contracted_item": 1})
+
+ po.append("items", {
+ "item_code": item_code,
+ "schedule_date": frappe.utils.add_days(frappe.flags.current_date, 7),
+ "qty": random.randint(10, 30)
+ })
+ po.set_missing_values()
+ try:
+ po.insert()
+ except InvalidCurrency:
+ return
- po.submit()
+ po.submit()
- # make material request for
- make_material_request(po.items[0].item_code, po.items[0].qty)
+ # make material request for
+ make_material_request(po.items[0].item_code, po.items[0].qty)
- # transfer material for sub-contract
- stock_entry = frappe.get_doc(make_stock_entry(po.name, po.items[0].item_code))
- stock_entry.from_warehouse = "Stores - WPL"
- stock_entry.to_warehouse = "Supplier - WPL"
- stock_entry.insert()
+ # transfer material for sub-contract
+ stock_entry = frappe.get_doc(make_stock_entry(po.name, po.items[0].item_code))
+ stock_entry.from_warehouse = "Stores - WPL"
+ stock_entry.to_warehouse = "Supplier - WPL"
+ stock_entry.insert()
diff --git a/erpnext/demo/user/schools.py b/erpnext/demo/user/schools.py
new file mode 100644
index 0000000..6388f9a
--- /dev/null
+++ b/erpnext/demo/user/schools.py
@@ -0,0 +1,97 @@
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+
+import frappe
+import random
+from frappe.utils import cstr
+from frappe.utils.make_random import get_random
+from datetime import timedelta
+from erpnext.schools.api import get_student_group_students, make_attendance_records, enroll_student, get_fee_schedule, collect_fees
+
+def work():
+ frappe.set_user(frappe.db.get_global('demo_schools_user'))
+ for d in xrange(20):
+ approve_random_student_applicant()
+ enroll_random_student(frappe.flags.current_date)
+ if frappe.flags.current_date.weekday()== 0:
+ make_course_schedule(frappe.flags.current_date, frappe.utils.add_days(frappe.flags.current_date, 5))
+ mark_student_attendance(frappe.flags.current_date)
+ make_fees()
+
+def mark_student_attendance(current_date):
+ status = ["Present", "Absent"]
+ for d in frappe.db.get_list("Course Schedule", filters={"schedule_date": current_date}, fields=("name", "student_group")):
+ students = get_student_group_students(d.student_group)
+ for stud in students:
+ make_attendance_records(stud.student, stud.student_name, d.name, status[weighted_choice([9,4])])
+
+def make_fees():
+ for d in range(1,10):
+ random_fee = get_random("Fees", {"paid_amount": 0})
+ collect_fees(random_fee, frappe.db.get_value("Fees", random_fee, "outstanding_amount"))
+
+def approve_random_student_applicant():
+ random_student = get_random("Student Applicant", {"application_status": "Applied"})
+ if random_student:
+ status = ["Approved", "Rejected"]
+ frappe.db.set_value("Student Applicant", random_student, "application_status", status[weighted_choice([9,3])])
+
+def enroll_random_student(current_date):
+ random_student = get_random("Student Applicant", {"application_status": "Approved"})
+ if random_student:
+ enrollment = enroll_student(random_student)
+ enrollment.academic_year = get_random("Academic Year")
+ enrollment.enrollment_date = current_date
+ fee_schedule = get_fee_schedule(enrollment.program)
+ for fee in fee_schedule:
+ enrollment.append("fees", fee)
+ enrollment.submit()
+ frappe.db.commit()
+ assign_student_group(enrollment.student, enrollment.program)
+
+def assign_student_group(student, program):
+ courses = []
+ for d in frappe.get_list("Program Course", fields=("course"), filters={"parent": program }):
+ courses.append(d.course)
+
+ for d in xrange(3):
+ course = random.choice(courses)
+ random_sg = get_random("Student Group", {"course": course})
+ if random_sg:
+ student_group = frappe.get_doc("Student Group", random_sg)
+ student_group.append("students", {"student": student})
+ student_group.save()
+ courses.remove(course)
+
+def make_course_schedule(start_date, end_date):
+ for d in frappe.db.get_list("Student Group"):
+ cs = frappe.new_doc("Scheduling Tool")
+ cs.student_group = d.name
+ cs.room = get_random("Room")
+ cs.instructor = get_random("Instructor")
+ cs.course_start_date = cstr(start_date)
+ cs.course_end_date = cstr(end_date)
+ day = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
+ for x in xrange(3):
+ random_day = random.choice(day)
+ cs.day = random_day
+ cs.from_time = timedelta(hours=(random.randrange(7, 17,1)))
+ cs.to_time = cs.from_time + timedelta(hours=1)
+ cs.schedule_course()
+ day.remove(random_day)
+
+
+def weighted_choice(weights):
+ totals = []
+ running_total = 0
+
+ for w in weights:
+ running_total += w
+ totals.append(running_total)
+
+ rnd = random.random() * running_total
+ for i, total in enumerate(totals):
+ if rnd < total:
+ return i
\ No newline at end of file
diff --git a/erpnext/demo/user/stock.py b/erpnext/demo/user/stock.py
index c86a11b..ac380f2 100644
--- a/erpnext/demo/user/stock.py
+++ b/erpnext/demo/user/stock.py
@@ -102,23 +102,21 @@
def make_sales_return_records():
for data in frappe.get_all('Delivery Note', fields=["name"], filters={"docstatus": 1}):
if random.random() < 0.2:
- print "dn"
try:
dn = make_sales_return(data.name)
dn.insert()
dn.submit()
frappe.db.commit()
- except Exception, e:
+ except Exception:
frappe.db.rollback()
def make_purchase_return_records():
for data in frappe.get_all('Purchase Receipt', fields=["name"], filters={"docstatus": 1}):
if random.random() < 0.2:
- print "purchase"
try:
pr = make_purchase_return(data.name)
pr.insert()
pr.submit()
frappe.db.commit()
- except Exception, e:
+ except Exception:
frappe.db.rollback()
diff --git a/erpnext/schools/api.py b/erpnext/schools/api.py
index 4649d0c..3554fe7 100644
--- a/erpnext/schools/api.py
+++ b/erpnext/schools/api.py
@@ -21,9 +21,8 @@
"field_map": {
"name": "student_applicant"
}
- }})
+ }}, ignore_permissions=True)
student.save()
-
program_enrollment = frappe.new_doc("Program Enrollment")
program_enrollment.student = student.name
program_enrollment.student_name = student.title