feat: gst fields in class student

This commit is contained in:
Jannat Patel
2023-08-23 13:00:54 +05:30
parent 04ed7f412f
commit 47c19b4e3d
11 changed files with 175 additions and 58 deletions

View File

@@ -7,16 +7,25 @@
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"student_details_section",
"student",
"column_break_oduu",
"student_name",
"username",
"address",
"payment_details_section",
"column_break_zvlp",
"amount",
"currency",
"column_break_clem",
"order_id",
"payment_id",
"payment_received"
"payment_received",
"address_details_section",
"address",
"pan",
"column_break_rqoj",
"gstin",
"gst_category"
],
"fields": [
{
@@ -78,12 +87,54 @@
"fieldname": "payment_received",
"fieldtype": "Check",
"label": "Payment Received"
},
{
"fieldname": "student_details_section",
"fieldtype": "Section Break",
"label": "Student Details"
},
{
"fieldname": "column_break_oduu",
"fieldtype": "Column Break"
},
{
"fieldname": "payment_details_section",
"fieldtype": "Section Break",
"label": "Payment Details"
},
{
"fieldname": "column_break_clem",
"fieldtype": "Column Break"
},
{
"fieldname": "address_details_section",
"fieldtype": "Section Break",
"label": "Address Details"
},
{
"fieldname": "pan",
"fieldtype": "Data",
"label": "PAN"
},
{
"fieldname": "column_break_rqoj",
"fieldtype": "Column Break"
},
{
"fieldname": "gstin",
"fieldtype": "Data",
"label": "GSTIN"
},
{
"fieldname": "gst_category",
"fieldtype": "Select",
"label": "GST Category"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2023-08-22 10:41:40.577437",
"modified": "2023-08-22 21:59:16.678547",
"modified_by": "Administrator",
"module": "LMS",
"name": "Class Student",

View File

@@ -185,6 +185,50 @@ def authenticate():
return response.json()["access_token"]
@frappe.whitelist()
def create_class(
title,
start_date,
end_date,
description=None,
prerequisite=None,
seat_count=0,
start_time=None,
end_time=None,
medium="Online",
category=None,
paid_class=0,
amount=0,
currency=None,
name=None,
):
frappe.only_for("Moderator")
if name:
class_details = frappe.get_doc("LMS Class", name)
else:
class_details = frappe.get_doc({"doctype": "LMS Class"})
class_details.update(
{
"title": title,
"start_date": start_date,
"end_date": end_date,
"description": description,
"prerequisite": prerequisite,
"seat_count": seat_count,
"start_time": start_time,
"end_time": end_time,
"medium": medium,
"category": category,
"paid_class": paid_class,
"amount": amount,
"currency": currency,
}
)
class_details.save()
return class_details
@frappe.whitelist()
def fetch_lessons(courses):
lessons = []

View File

@@ -987,5 +987,5 @@ def add_student_to_class(address, response, classname, client):
return f"/classes/{classname}"
except Exception as e:
frappe.throw(
_("Error during payment: {0}. Please contact the Administrator.").format(e)
_("Error during payment: {0} Please contact the Administrator.").format(e)
)

View File

@@ -354,6 +354,7 @@ const open_class_dialog = () => {
default: class_info && class_info.currency,
mandatory_depends_on: "paid_class",
depends_on: "paid_class",
only_select: 1,
},
],
primary_action_label: __("Save"),
@@ -365,20 +366,15 @@ const open_class_dialog = () => {
};
const save_class = (values) => {
let method, args;
let args = {};
if (class_info) {
method = "frappe.client.save";
args = Object.assign(class_info, values);
} else {
method = "frappe.client.insert";
args = values;
args.doctype = "LMS Class";
}
frappe.call({
method: method,
args: {
doc: args,
},
method: "lms.lms.doctype.lms_class.lms_class.create_class",
args: args,
callback: (r) => {
if (r.message) {
frappe.show_alert({

View File

@@ -20,7 +20,7 @@
{{ _("Order Details") }}
</div>
<div>
{{ _("Enter the billing information and complete the payment to purchase this {0}.").format(module) }}
{{ _("Enter the billing information to complete the payment.").format(module) }}
</div>
</div>
{% endmacro %}
@@ -59,11 +59,4 @@
{%- block script %}
{{ super() }}
<script src="https://checkout.razorpay.com/v1/checkout.js"></script>
<script>
frappe.boot.user = {
"can_create": [],
"can_select": ["Country"],
"can_read": ["Country"]
};
</script>
{% endblock %}

View File

@@ -44,6 +44,7 @@ const setup_billing = () => {
fieldname: "country",
options: "Country",
reqd: 1,
only_select: 1,
},
{
fieldtype: "Data",
@@ -57,6 +58,18 @@ const setup_billing = () => {
fieldname: "phone",
reqd: 1,
},
{
fieldtype: "Data",
fieldname: "gstin",
label: __("GSTIN"),
depends_on: (doc) => console.log(doc.country),
},
{
fieldtype: "Data",
fieldname: "pan",
label: __("PAN"),
depends_on: (doc) => console.log(doc.country),
},
],
body: $("#billing-form").get(0),
});

View File

@@ -600,26 +600,8 @@
{%- block script %}
{{ super() }}
{% if is_moderator %}
<script>
frappe.boot.user = {
"can_create": [],
"can_select": ["User", "LMS Assignment", "LMS Quiz"],
"can_read": ["User", "LMS Assignment", "LMS Quiz"]
};
frappe.boot.single_types = []
</script>
{% else %}
<script>
frappe.boot.user= {
"can_create": [],
"can_select": ["LMS Course"],
"can_read": ["LMS Course"]
};
let courses = {{ course_list | json }};
</script>
{% endif %}
{% endblock %}

View File

@@ -1,11 +1,13 @@
frappe.ready(() => {
let self = this;
frappe.require("controls.bundle.js");
if ($("#live-class-form").length) {
frappe.require("controls.bundle.js", () => {
setTimeout(() => {
make_live_class_form();
});
}, 1000);
}
$(".btn-add-student").click((e) => {
show_student_modal(e);
});
@@ -308,12 +310,14 @@ const show_course_modal = () => {
label: __("Course"),
fieldname: "course",
reqd: 1,
only_select: 1,
},
{
fieldtype: "Link",
options: "Course Evaluator",
label: __("Course Evaluator"),
fieldname: "evaluator",
only_select: 1,
},
],
primary_action_label: __("Add"),
@@ -385,6 +389,7 @@ const show_student_modal = () => {
label: __("Student"),
fieldname: "student",
reqd: 1,
only_select: 1,
filters: {
ignore_user_type: 1,
},
@@ -463,6 +468,7 @@ const show_assessment_modal = (e) => {
label: __("Assessment Type"),
fieldname: "assessment_type",
reqd: 1,
only_select: 1,
filters: {
name: ["in", ["LMS Assignment", "LMS Quiz"]],
},
@@ -474,6 +480,7 @@ const show_assessment_modal = (e) => {
label: __("Assessment"),
fieldname: "assessment_name",
reqd: 1,
only_select: 1,
},
{
fieldtype: "Section Break",

View File

@@ -8,10 +8,10 @@
<div class="common-page-style lms-page-style">
{{ ClassHeader(class_info) }}
<div class="container">
{{ CourseHeaderOverlay(class_info) }}
{{ CourseHeaderOverlay(class_info, courses, students) }}
<div class="pt-10">
{{ Prerequisites(class_info) }}
{{ CourseList(class_info) }}
{{ CourseList(courses) }}
</div>
</div>
</div>
@@ -22,7 +22,7 @@
<div class="container">
<div class="course-card-wide">
{{ BreadCrumb(class_info) }}
{{ ClassHeaderDetails(class_info) }}
{{ ClassHeaderDetails(class_info, courses, students) }}
</div>
</div>
</div>
@@ -40,15 +40,15 @@
</article>
{% endmacro %}
{% macro ClassHeaderDetails(class_info) %}
{% macro ClassHeaderDetails(class_info, courses, students) %}
<div class="class-details" data-class="{{ class_info.name }}">
<div class="flex align-center">
<span>
{{ class_info.courses | length }} {{ _("Courses") }}
{{ courses | length }} {{ _("Courses") }}
</span>
<span class="px-2"> · </span>
<span>
{{ class_info.students | length }} {{ _("Students") }}
{{ students | length }} {{ _("Students") }}
</span>
</div>
@@ -88,7 +88,7 @@
</div>
{% endmacro %}
{% macro CourseHeaderOverlay(class_info) %}
{% macro CourseHeaderOverlay(class_info, courses, students) %}
<div class="course-overlay-card class-overlay">
<div class="course-overlay-content">
@@ -102,14 +102,14 @@
<svg class="icon icon-md mr-1">
<use href="#icon-education"></use>
</svg>
{{ class_info.courses | length }} {{ _("Courses") }}
{{ courses | length }} {{ _("Courses") }}
</div>
<div class="vertically-center mt-2">
<svg class="icon icon-md mr-1">
<use class="" href="#icon-users">
</svg>
{{ class_info.students | length }} {{ _("Students") }}
{{ students | length }} {{ _("Students") }}
</div>
<div class="mt-2">
@@ -177,14 +177,14 @@
{% endmacro %}
{% macro CourseList(class_info) %}
{% macro CourseList(courses) %}
<div>
<div class="page-title">
{{ _("Courses") }}
</div>
{% if class_info.courses | length %}
{% if courses | length %}
<div class="cards-parent mt-2">
{% for course in class_info.courses %}
{% for course in courses %}
<div class="h-100">
{{ widgets.CourseCard(course=course, read_only=False) }}
<button class="btn icon-btn btn-default btn-block btn-remove-course" data-course="{{ course.name }}">

View File

@@ -7,15 +7,46 @@ def get_context(context):
context.no_cache = 1
class_name = frappe.form_dict["classname"]
context.class_info = frappe.get_doc("LMS Class", class_name)
context.class_info = frappe.db.get_value(
"LMS Class",
class_name,
[
"name",
"title",
"description",
"prerequisite",
"start_date",
"end_date",
"paid_class",
"amount",
"currency",
"start_time",
"end_time",
],
as_dict=1,
)
for course in context.class_info.courses:
context.courses = frappe.get_all(
"Class Course",
{"parent": class_name},
["name", "course", "title"],
order_by="creation desc",
)
for course in context.courses:
course.update(
frappe.db.get_value(
"LMS Course", course.course, ["name", "short_introduction", "image"], as_dict=1
)
)
context.students = frappe.get_all(
"Class Student",
{"parent": class_name},
["name", "student", "student_name", "username"],
order_by="creation desc",
)
context.is_moderator = has_course_moderator_role()
context.is_evaluator = has_course_evaluator_role()
context.is_student = is_student(class_name)

View File

@@ -106,12 +106,12 @@
{% endif %}
{% if show_price and class.paid_class %}
<div class="bold-heading">
<div class="bold-heading mb-2">
{{ frappe.utils.fmt_money(class.amount, 0, class.currency) }}
</div>
{% endif %}
<div class="mt-auto mb-1">
<div class="mt-auto mb-2">
<svg class="icon icon-sm">
<use href="#icon-calendar"></use>
</svg>
@@ -123,14 +123,14 @@
</span>
</div>
<div class="mb-1">
<div class="mb-2">
<svg class="icon icon-md">
<use href="#icon-education"></use>
</svg>
{{ course_count }} {{ _("Courses") }}
</div>
<div class="mb-1">
<div class="mb-2">
<svg class="icon icon-md">
<use href="#icon-users"></use>
</svg>