feat: capture gst information

This commit is contained in:
Jannat Patel
2023-08-24 22:15:55 +05:30
parent 47c19b4e3d
commit d5f10db250
18 changed files with 371 additions and 271 deletions

View File

@@ -9,23 +9,10 @@
"field_order": [ "field_order": [
"student_details_section", "student_details_section",
"student", "student",
"payment",
"column_break_oduu", "column_break_oduu",
"student_name", "student_name",
"username", "username"
"payment_details_section",
"column_break_zvlp",
"amount",
"currency",
"column_break_clem",
"order_id",
"payment_id",
"payment_received",
"address_details_section",
"address",
"pan",
"column_break_rqoj",
"gstin",
"gst_category"
], ],
"fields": [ "fields": [
{ {
@@ -51,43 +38,6 @@
"label": "Username", "label": "Username",
"read_only": 1 "read_only": 1
}, },
{
"fieldname": "column_break_zvlp",
"fieldtype": "Column Break"
},
{
"fieldname": "address",
"fieldtype": "Link",
"label": "Address",
"options": "Address"
},
{
"fieldname": "amount",
"fieldtype": "Currency",
"label": "Amount"
},
{
"fieldname": "currency",
"fieldtype": "Link",
"label": "Currency",
"options": "Currency"
},
{
"fieldname": "order_id",
"fieldtype": "Data",
"label": "Order ID"
},
{
"fieldname": "payment_id",
"fieldtype": "Data",
"label": "Payment ID"
},
{
"default": "0",
"fieldname": "payment_received",
"fieldtype": "Check",
"label": "Payment Received"
},
{ {
"fieldname": "student_details_section", "fieldname": "student_details_section",
"fieldtype": "Section Break", "fieldtype": "Section Break",
@@ -98,43 +48,16 @@
"fieldtype": "Column Break" "fieldtype": "Column Break"
}, },
{ {
"fieldname": "payment_details_section", "fieldname": "payment",
"fieldtype": "Section Break", "fieldtype": "Link",
"label": "Payment Details" "label": "Payment",
}, "options": "LMS Payment"
{
"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, "index_web_pages_for_search": 1,
"istable": 1, "istable": 1,
"links": [], "links": [],
"modified": "2023-08-22 21:59:16.678547", "modified": "2023-08-24 17:48:53.045539",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "Class Student", "name": "Class Student",

View File

@@ -7,22 +7,15 @@
"field_order": [ "field_order": [
"course", "course",
"member_type", "member_type",
"batch", "payment",
"column_break_3", "column_break_3",
"member", "member",
"member_name", "member_name",
"member_username", "member_username",
"billing_information_section",
"address",
"amount",
"currency",
"column_break_rvzn",
"order_id",
"payment_id",
"payment_received",
"section_break_8", "section_break_8",
"cohort", "cohort",
"subgroup", "subgroup",
"batch",
"column_break_12", "column_break_12",
"current_lesson", "current_lesson",
"progress", "progress",
@@ -122,52 +115,15 @@
"fieldtype": "Section Break" "fieldtype": "Section Break"
}, },
{ {
"fieldname": "billing_information_section", "fieldname": "payment",
"fieldtype": "Section Break",
"label": "Billing Information"
},
{
"fieldname": "address",
"fieldtype": "Link", "fieldtype": "Link",
"label": "Address", "label": "Payment",
"options": "Address" "options": "LMS Payment"
},
{
"default": "0",
"fieldname": "payment_received",
"fieldtype": "Check",
"label": "Payment Received"
},
{
"fieldname": "column_break_rvzn",
"fieldtype": "Column Break"
},
{
"fieldname": "order_id",
"fieldtype": "Data",
"label": "Order ID"
},
{
"fieldname": "payment_id",
"fieldtype": "Data",
"label": "Payment ID"
},
{
"fieldname": "amount",
"fieldtype": "Data",
"label": "Amount",
"options": "currency"
},
{
"fieldname": "currency",
"fieldtype": "Link",
"label": "Currency",
"options": "Currency"
} }
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"links": [], "links": [],
"modified": "2023-08-17 13:52:49.450499", "modified": "2023-08-24 17:52:35.487141",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "LMS Batch Membership", "name": "LMS Batch Membership",

View File

@@ -21,7 +21,7 @@
"seat_count", "seat_count",
"section_break_6", "section_break_6",
"description", "description",
"prerequisite", "class_details",
"students", "students",
"courses", "courses",
"section_break_gsac", "section_break_gsac",
@@ -188,15 +188,15 @@
"options": "Currency" "options": "Currency"
}, },
{ {
"fieldname": "prerequisite", "fieldname": "class_details",
"fieldtype": "Small Text", "fieldtype": "Text Editor",
"label": "Prerequisite", "label": "Class Details",
"reqd": 1 "reqd": 1
} }
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"links": [], "links": [],
"modified": "2023-08-22 11:53:22.248596", "modified": "2023-08-23 17:35:42.750754",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "LMS Class", "name": "LMS Class",

View File

@@ -191,7 +191,7 @@ def create_class(
start_date, start_date,
end_date, end_date,
description=None, description=None,
prerequisite=None, class_details=None,
seat_count=0, seat_count=0,
start_time=None, start_time=None,
end_time=None, end_time=None,
@@ -204,17 +204,17 @@ def create_class(
): ):
frappe.only_for("Moderator") frappe.only_for("Moderator")
if name: if name:
class_details = frappe.get_doc("LMS Class", name) doc = frappe.get_doc("LMS Class", name)
else: else:
class_details = frappe.get_doc({"doctype": "LMS Class"}) doc = frappe.get_doc({"doctype": "LMS Class"})
class_details.update( doc.update(
{ {
"title": title, "title": title,
"start_date": start_date, "start_date": start_date,
"end_date": end_date, "end_date": end_date,
"description": description, "description": description,
"prerequisite": prerequisite, "class_details": class_details,
"seat_count": seat_count, "seat_count": seat_count,
"start_time": start_time, "start_time": start_time,
"end_time": end_time, "end_time": end_time,
@@ -225,8 +225,8 @@ def create_class(
"currency": currency, "currency": currency,
} }
) )
class_details.save() doc.save()
return class_details return doc
@frappe.whitelist() @frappe.whitelist()

View File

View File

@@ -0,0 +1,8 @@
// Copyright (c) 2023, Frappe and contributors
// For license information, please see license.txt
// frappe.ui.form.on("LMS Payment", {
// refresh(frm) {
// },
// });

View File

@@ -0,0 +1,139 @@
{
"actions": [],
"allow_rename": 1,
"autoname": "format:PAY-{#####}",
"creation": "2023-08-24 17:46:52.065763",
"default_view": "List",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"member",
"column_break_rqkd",
"billing_name",
"payment_received",
"payment_details_section",
"amount",
"currency",
"column_break_yxpl",
"order_id",
"payment_id",
"billing_details_section",
"address",
"column_break_monu",
"gstin",
"pan"
],
"fields": [
{
"fieldname": "order_id",
"fieldtype": "Data",
"label": "Order ID"
},
{
"fieldname": "payment_id",
"fieldtype": "Data",
"label": "Payment ID"
},
{
"fieldname": "amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Amount"
},
{
"fieldname": "currency",
"fieldtype": "Link",
"label": "Currency",
"options": "Currency"
},
{
"fieldname": "column_break_rqkd",
"fieldtype": "Column Break"
},
{
"fieldname": "gstin",
"fieldtype": "Data",
"label": "GSTIN"
},
{
"fieldname": "pan",
"fieldtype": "Data",
"label": "PAN"
},
{
"fieldname": "address",
"fieldtype": "Link",
"label": "Address",
"options": "Address"
},
{
"default": "0",
"fieldname": "payment_received",
"fieldtype": "Check",
"label": "Payment Received"
},
{
"fetch_from": "user.full_name",
"fieldname": "billing_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Billing Name",
"reqd": 1
},
{
"fieldname": "payment_details_section",
"fieldtype": "Section Break",
"label": "Payment Details"
},
{
"fieldname": "column_break_yxpl",
"fieldtype": "Column Break"
},
{
"fieldname": "billing_details_section",
"fieldtype": "Section Break",
"label": "Billing Details"
},
{
"fieldname": "column_break_monu",
"fieldtype": "Column Break"
},
{
"fieldname": "member",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Member",
"options": "User",
"reqd": 1
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-08-24 22:08:12.294960",
"modified_by": "Administrator",
"module": "LMS",
"name": "LMS Payment",
"naming_rule": "Expression",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"show_title_field_in_link": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"title_field": "billing_name"
}

View File

@@ -0,0 +1,9 @@
# Copyright (c) 2023, Frappe and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class LMSPayment(Document):
pass

View File

@@ -0,0 +1,9 @@
# Copyright (c) 2023, Frappe and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestLMSPayment(FrappeTestCase):
pass

View File

@@ -835,24 +835,7 @@ def get_payment_options(doctype, docname, phone):
frappe.throw(_("Invalid document provided.")) frappe.throw(_("Invalid document provided."))
validate_phone_number(phone, True) validate_phone_number(phone, True)
if doctype == "LMS Course": details = get_details(doctype, docname)
details = frappe.db.get_value(
"LMS Course",
docname,
["name", "title", "paid_course", "currency", "course_price as amount"],
as_dict=True,
)
if not details.paid_course:
frappe.throw(_("This course is free."))
else:
details = frappe.db.get_value(
"LMS Class",
docname,
["name", "title", "paid_class", "currency", "amount"],
as_dict=True,
)
if not details.paid_class:
frappe.throw(_("To join this class, please contact the Administrator."))
razorpay_key = frappe.db.get_single_value("LMS Settings", "razorpay_key") razorpay_key = frappe.db.get_single_value("LMS Settings", "razorpay_key")
client = get_client() client = get_client()
@@ -874,8 +857,30 @@ def get_payment_options(doctype, docname, phone):
return options return options
def get_details(doctype, docname):
if doctype == "LMS Course":
details = frappe.db.get_value(
"LMS Course",
docname,
["name", "title", "paid_course", "currency", "course_price as amount"],
as_dict=True,
)
if not details.paid_course:
frappe.throw(_("This course is free."))
else:
details = frappe.db.get_value(
"LMS Class",
docname,
["name", "title", "paid_class", "currency", "amount"],
as_dict=True,
)
if not details.paid_class:
frappe.throw(_("To join this class, please contact the Administrator."))
return details
def save_address(address): def save_address(address):
address = json.loads(address)
address.update( address.update(
{ {
"address_title": frappe.db.get_value("User", frappe.session.user, "full_name"), "address_title": frappe.db.get_value("User", frappe.session.user, "full_name"),
@@ -930,62 +935,76 @@ def verify_payment(response, doctype, docname, address, order_id):
} }
) )
payment = record_payment(address, response, client, doctype, docname)
if doctype == "LMS Course": if doctype == "LMS Course":
return create_membership(address, response, docname, client) return create_membership(docname, payment)
else: else:
return add_student_to_class(address, response, docname, client) return add_student_to_class(docname, payment)
def create_membership(address, response, course, client): def record_payment(address, response, client, doctype, docname):
address = frappe._dict(json.loads(address))
address_name = save_address(address)
payment_details = get_payment_details(client, response, doctype, docname)
payment_doc = frappe.new_doc("LMS Payment")
payment_doc.update(
{
"member": frappe.session.user,
"billing_name": address.billing_name,
"address": address_name,
"payment_received": 1,
"order_id": response["razorpay_order_id"],
"payment_id": response["razorpay_payment_id"],
"amount": payment_details["amount"],
"currency": payment_details["currency"],
"gstin": address.gstin,
"pan": address.pan,
}
)
payment_doc.save(ignore_permissions=True)
return payment_doc.name
def get_payment_details(client, response, doctype, docname):
try: try:
address_name = save_address(address)
payment = client.payment.fetch(response["razorpay_payment_id"]) payment = client.payment.fetch(response["razorpay_payment_id"])
membership = frappe.new_doc("LMS Batch Membership")
membership.update(
{
"member": frappe.session.user,
"course": course,
"address": address_name,
"payment_received": 1,
"order_id": response["razorpay_order_id"],
"payment_id": response["razorpay_payment_id"],
"amount": payment["amount"] / 100,
"currency": payment["currency"],
}
)
membership.save(ignore_permissions=True)
return f"/courses/{course}/learn/1.1"
except Exception as e: except Exception as e:
frappe.throw( frappe.log_error(e, "Error during payment fetch")
_("Error during payment: {0}. Please contact the Administrator.").format(e)
) if payment:
amount = payment["amount"] / 100
currency = payment["currency"]
else:
amount_field = "course_price" if doctype == "LMS Course" else "amount"
amount = frappe.db.get_value(doctype, docname, amount_field)
currency = frappe.db.get_value(doctype, docname, "currency")
return {
"amount": amount,
"currency": currency,
}
def add_student_to_class(address, response, classname, client): def create_membership(course, payment):
try: membership = frappe.new_doc("LMS Batch Membership")
address_name = save_address(address) membership.update(
payment = client.payment.fetch(response["razorpay_payment_id"]) {"member": frappe.session.user, "course": course, "payment": payment}
student = frappe.new_doc("Class Student") )
membership.save(ignore_permissions=True)
return f"/courses/{course}/learn/1.1"
student.update(
{ def add_student_to_class(classname, payment):
"student": frappe.session.user, student = frappe.new_doc("Class Student")
"parent": classname, student.update(
"parenttype": "LMS Class", {
"parentfield": "students", "student": frappe.session.user,
"address": address_name, "payment": payment,
"amount": payment["amount"] / 100, "parent": classname,
"currency": payment["currency"], "parenttype": "LMS Class",
"payment_received": 1, "parentfield": "students",
"order_id": response["razorpay_order_id"], }
"payment_id": response["razorpay_payment_id"], )
} student.save(ignore_permissions=True)
) return f"/classes/{classname}"
student.save(ignore_permissions=True)
return f"/classes/{classname}"
except Exception as e:
frappe.throw(
_("Error during payment: {0} Please contact the Administrator.").format(e)
)

View File

@@ -2188,10 +2188,6 @@ select {
border-bottom: none; border-bottom: none;
} }
.awesomplete ul li:last-child {
display: none;
}
.students-parent { .students-parent {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, 150px); grid-template-columns: repeat(auto-fill, 150px);

View File

@@ -321,10 +321,10 @@ const open_class_dialog = () => {
reqd: 1, reqd: 1,
}, },
{ {
fieldtype: "Small Text", fieldtype: "Text Editor",
label: __("Prerequisite"), label: __("Class Details"),
fieldname: "prerequisite", fieldname: "class_details",
default: class_info && class_info.prerequisite, default: class_info && class_info.class_details,
reqd: 1, reqd: 1,
}, },
{ {

View File

@@ -13,6 +13,12 @@ frappe.ready(() => {
const setup_billing = () => { const setup_billing = () => {
this.billing = new frappe.ui.FieldGroup({ this.billing = new frappe.ui.FieldGroup({
fields: [ fields: [
{
fieldtype: "Data",
label: __("Billing Name"),
fieldname: "billing_name",
reqd: 1,
},
{ {
fieldtype: "Data", fieldtype: "Data",
label: __("Address Line 1"), label: __("Address Line 1"),
@@ -30,14 +36,14 @@ const setup_billing = () => {
fieldname: "city", fieldname: "city",
reqd: 1, reqd: 1,
}, },
{
fieldtype: "Column Break",
},
{ {
fieldtype: "Data", fieldtype: "Data",
label: __("State/Province"), label: __("State/Province"),
fieldname: "state", fieldname: "state",
}, },
{
fieldtype: "Column Break",
},
{ {
fieldtype: "Link", fieldtype: "Link",
label: __("Country"), label: __("Country"),
@@ -58,17 +64,25 @@ const setup_billing = () => {
fieldname: "phone", fieldname: "phone",
reqd: 1, reqd: 1,
}, },
{
fieldtype: "Section Break",
label: __("GST Details"),
fieldname: "gst_details",
depends_on: "eval:doc.country === 'India'",
},
{ {
fieldtype: "Data", fieldtype: "Data",
fieldname: "gstin",
label: __("GSTIN"), label: __("GSTIN"),
depends_on: (doc) => console.log(doc.country), fieldname: "gstin",
},
{
fieldtype: "Column Break",
fieldname: "gst_details_break",
}, },
{ {
fieldtype: "Data", fieldtype: "Data",
fieldname: "pan", fieldname: "pan",
label: __("PAN"), label: __("PAN"),
depends_on: (doc) => console.log(doc.country),
}, },
], ],
body: $("#billing-form").get(0), body: $("#billing-form").get(0),

View File

@@ -39,7 +39,7 @@ def get_context(context):
"paid_class", "paid_class",
"amount", "amount",
"currency", "currency",
"prerequisite", "class_details",
], ],
as_dict=True, as_dict=True,
) )

View File

@@ -10,7 +10,7 @@
<div class="container"> <div class="container">
{{ CourseHeaderOverlay(class_info, courses, students) }} {{ CourseHeaderOverlay(class_info, courses, students) }}
<div class="pt-10"> <div class="pt-10">
{{ Prerequisites(class_info) }} {{ ClassDetails(class_info) }}
{{ CourseList(courses) }} {{ CourseList(courses) }}
</div> </div>
</div> </div>
@@ -42,15 +42,6 @@
{% macro ClassHeaderDetails(class_info, courses, students) %} {% macro ClassHeaderDetails(class_info, courses, students) %}
<div class="class-details" data-class="{{ class_info.name }}"> <div class="class-details" data-class="{{ class_info.name }}">
<div class="flex align-center">
<span>
{{ courses | length }} {{ _("Courses") }}
</span>
<span class="px-2"> · </span>
<span>
{{ students | length }} {{ _("Students") }}
</span>
</div>
<div class="page-title"> <div class="page-title">
{{ class_info.title }} {{ class_info.title }}
@@ -92,6 +83,19 @@
<div class="course-overlay-card class-overlay"> <div class="course-overlay-card class-overlay">
<div class="course-overlay-content"> <div class="course-overlay-content">
{% if class_info.seat_count %}
{% if seats_left %}
<div class="indicator-pill green pull-right">
{{ _("Seats Available") }}: {{ seats_left }}
</div>
{% else %}
<div class="indicator-pill red pull-right">
{{ _("No seats left") }}
</div>
{% endif %}
{% endif %}
{% if class_info.paid_class %} {% if class_info.paid_class %}
<div class="bold-heading"> <div class="bold-heading">
{{ frappe.utils.fmt_money(class_info.amount, 0, class_info.currency) }} {{ frappe.utils.fmt_money(class_info.amount, 0, class_info.currency) }}
@@ -105,13 +109,6 @@
{{ courses | length }} {{ _("Courses") }} {{ courses | length }} {{ _("Courses") }}
</div> </div>
<div class="vertically-center mt-2">
<svg class="icon icon-md mr-1">
<use class="" href="#icon-users">
</svg>
{{ students | length }} {{ _("Students") }}
</div>
<div class="mt-2"> <div class="mt-2">
<svg class="icon icon-sm"> <svg class="icon icon-sm">
<use href="#icon-calendar"></use> <use href="#icon-calendar"></use>
@@ -144,7 +141,8 @@
{{ _("Checkout Class") }} {{ _("Checkout Class") }}
</a> </a>
{% elif class_info.paid_class %} {% elif class_info.paid_class %}
<a class="btn btn-primary wide-button" href="/billing/class/{{ class_info.name }}"> <a class="btn btn-primary wide-button {% if class_info.seat_count and not seats_left %} hide {% endif %}"
href="/billing/class/{{ class_info.name }}">
{{ _("Register Now") }} {{ _("Register Now") }}
</a> </a>
{% else %} {% else %}
@@ -165,13 +163,10 @@
{% endmacro %} {% endmacro %}
{% macro Prerequisites(class_info) %} {% macro ClassDetails(class_info) %}
<div class="course-description-section w-50"> <div class="course-description-section w-50">
<div class="page-title">
{{ _("Prerequisite Knowledge") }}
</div>
<div class="mt-2"> <div class="mt-2">
{{ class_info.prerequisite }} {{ class_info.class_details }}
</div> </div>
</div> </div>
{% endmacro %} {% endmacro %}

View File

@@ -14,7 +14,7 @@ def get_context(context):
"name", "name",
"title", "title",
"description", "description",
"prerequisite", "class_details",
"start_date", "start_date",
"end_date", "end_date",
"paid_class", "paid_class",
@@ -22,6 +22,7 @@ def get_context(context):
"currency", "currency",
"start_time", "start_time",
"end_time", "end_time",
"seat_count",
], ],
as_dict=1, as_dict=1,
) )
@@ -40,12 +41,8 @@ def get_context(context):
) )
) )
context.students = frappe.get_all( context.student_count = frappe.db.count("Class Student", {"parent": class_name})
"Class Student", context.seats_left = context.class_info.seat_count - context.student_count
{"parent": class_name},
["name", "student", "student_name", "username"],
order_by="creation desc",
)
context.is_moderator = has_course_moderator_role() context.is_moderator = has_course_moderator_role()
context.is_evaluator = has_course_evaluator_role() context.is_evaluator = has_course_evaluator_role()

View File

@@ -90,11 +90,21 @@
{% macro ClassCards(classes, show_price=False) %} {% macro ClassCards(classes, show_price=False) %}
<div class="lms-card-parent"> <div class="lms-card-parent">
{% for class in classes %} {% for class in classes %}
{% set course_count = frappe.db.count("Class Course", {"parent": class.name}) %}
{% set student_count = frappe.db.count("Class Student", {"parent": class.name}) %}
<div class="common-card-style column-card" style="min-height: 150px;"> <div class="common-card-style column-card" style="min-height: 150px;">
{% if class.seat_count %}
{% if class.seats_left > 0 %}
<div class="indicator-pill green align-self-start mb-2">
{{ _("Seats Available") }}: {{ class.seats_left }}
</div>
{% else %}
<div class="indicator-pill red align-self-start mb-2">
{{ _("No Seats Left") }}
</div>
{% endif %}
{% endif %}
<div class="bold-heading"> <div class="bold-heading">
{{ class.title }} {{ class.title }}
</div> </div>
@@ -127,15 +137,15 @@
<svg class="icon icon-md"> <svg class="icon icon-md">
<use href="#icon-education"></use> <use href="#icon-education"></use>
</svg> </svg>
{{ course_count }} {{ _("Courses") }} {{ class.course_count }} {{ _("Courses") }}
</div> </div>
<div class="mb-2"> <!-- <div class="mb-2">
<svg class="icon icon-md"> <svg class="icon icon-md">
<use href="#icon-users"></use> <use href="#icon-users"></use>
</svg> </svg>
{{ student_count }} {{ _("Students") }} {{ student_count }} {{ _("Students") }}
</div> </div> -->
{% if is_student(class.name) %} {% if is_student(class.name) %}
<a class="stretched-link" href="/classes/{{ class.name }}"></a> <a class="stretched-link" href="/classes/{{ class.name }}"></a>

View File

@@ -20,10 +20,17 @@ def get_context(context):
"currency", "currency",
"seat_count", "seat_count",
], ],
order_by="start_date",
) )
past_classes, upcoming_classes = [], [] past_classes, upcoming_classes = [], []
for class_ in classes: for class_ in classes:
class_.student_count = frappe.db.count("Class Student", {"parent": class_.name})
class_.course_count = frappe.db.count("Class Course", {"parent": class_.name})
class_.seats_left = (
class_.seat_count - class_.student_count if class_.seat_count else None
)
print(class_.seat_count, class_.student_count, class_.seats_left)
if getdate(class_.start_date) < getdate(): if getdate(class_.start_date) < getdate():
past_classes.append(class_) past_classes.append(class_)
else: else:
@@ -39,13 +46,31 @@ def get_context(context):
) )
for class_ in my_classes: for class_ in my_classes:
my_classes_info.append( class_info = frappe.db.get_value(
frappe.db.get_value( "LMS Class",
"LMS Class", class_,
class_, [
["name", "title", "start_date", "end_date", "paid_class", "seat_count"], "name",
as_dict=True, "title",
) "description",
"start_date",
"end_date",
"paid_class",
"amount",
"currency",
"seat_count",
],
as_dict=True,
) )
class_info.student_count = frappe.db.count(
"Class Student", {"parent": class_info.name}
)
class_info.course_count = frappe.db.count(
"Class Course", {"parent": class_info.name}
)
class_info.seats_left = class_info.seat_count - class_info.student_count
my_classes_info.append(class_info)
context.my_classes = my_classes_info context.my_classes = my_classes_info