From 91783757e4888fea0ecdd461b62d970c56073863 Mon Sep 17 00:00:00 2001 From: Casey Date: Fri, 6 Feb 2026 08:07:18 -0600 Subject: [PATCH] payment pages working --- custom_ui/events/jobs.py | 7 + custom_ui/events/payments.py | 2 +- custom_ui/events/sales_order.py | 4 +- custom_ui/hooks.py | 3 + custom_ui/services/stripe_service.py | 4 +- custom_ui/www/cancelled_payment.html | 4 - custom_ui/www/payment_cancelled.html | 141 ++++++++++++ custom_ui/www/payment_cancelled.py | 0 custom_ui/www/payment_success.html | 212 ++++++++++++++++++ custom_ui/www/payment_success.py | 18 ++ custom_ui/www/successful_payment.html | 4 - .../calendar/jobs/SNWProjectCalendar.vue | 21 +- 12 files changed, 402 insertions(+), 18 deletions(-) delete mode 100644 custom_ui/www/cancelled_payment.html create mode 100644 custom_ui/www/payment_cancelled.html create mode 100644 custom_ui/www/payment_cancelled.py create mode 100644 custom_ui/www/payment_success.html create mode 100644 custom_ui/www/payment_success.py delete mode 100644 custom_ui/www/successful_payment.html diff --git a/custom_ui/events/jobs.py b/custom_ui/events/jobs.py index de0d9ff..c8cb80e 100644 --- a/custom_ui/events/jobs.py +++ b/custom_ui/events/jobs.py @@ -81,6 +81,13 @@ def before_save(doc, method): def after_save(doc, method): print("DEBUG: After Save Triggered for Project:", doc.name) + if doc.ready_to_schedule: + service_apt_ready_to_schedule = frappe.get_value("Service Address 2", doc.service_appointment, "ready_to_schedule") + if not service_apt_ready_to_schedule: + print("DEBUG: Project is ready to schedule, setting Service Appointment to ready to schedule.") + service_apt_doc = frappe.get_doc("Service Address 2", doc.service_appointment) + service_apt_doc.ready_to_schedule = 1 + service_apt_doc.save(ignore_permissions=True) if doc.project_template == "SNW Install": print("DEBUG: Project template is SNW Install, updating Address Job Status based on Project status") status_mapping = { diff --git a/custom_ui/events/payments.py b/custom_ui/events/payments.py index f603fca..f4eb2a5 100644 --- a/custom_ui/events/payments.py +++ b/custom_ui/events/payments.py @@ -9,7 +9,7 @@ def on_submit(doc, method): if so_ref: so_doc = frappe.get_doc("Sales Order", so_ref.reference_name) if so_doc.requires_half_payment: - is_paid = doc.custom_halfdown_amount <= doc.advance_paid or doc.advance_paid >= so_doc.grand_total / 2 + is_paid = so_doc.custom_halfdown_amount <= so_doc.advance_paid or so_doc.advance_paid >= so_doc.grand_total / 2 if is_paid and not so_doc.custom_halfdown_is_paid: print("DEBUG: Sales Order requires half payment and it has not been marked as paid, marking it as paid now.") so_doc.custom_halfdown_is_paid = 1 diff --git a/custom_ui/events/sales_order.py b/custom_ui/events/sales_order.py index ed51bba..c2ef402 100644 --- a/custom_ui/events/sales_order.py +++ b/custom_ui/events/sales_order.py @@ -151,7 +151,9 @@ def on_update_after_submit(doc, method): project_is_scheduable = frappe.get_value("Project", doc.project, "ready_to_schedule") if not project_is_scheduable: print("DEBUG: Half-down payment made, setting Project to ready to schedule.") - frappe.set_value("Project", doc.project, "ready_to_schedule", 1) + project_doc = frappe.get_doc("Project", doc.project) + project_doc.ready_to_schedule = 1 + project_doc.save() diff --git a/custom_ui/hooks.py b/custom_ui/hooks.py index 6cfcf77..ec8f716 100644 --- a/custom_ui/hooks.py +++ b/custom_ui/hooks.py @@ -204,6 +204,9 @@ doc_events = { "before_save": "custom_ui.events.service_appointment.before_save", "after_insert": "custom_ui.events.service_appointment.after_insert", "on_update": "custom_ui.events.service_appointment.on_update" + }, + "Payment Entry": { + "on_submit": "custom_ui.events.payments.on_submit" } } diff --git a/custom_ui/services/stripe_service.py b/custom_ui/services/stripe_service.py index ed3d2c7..6120af3 100644 --- a/custom_ui/services/stripe_service.py +++ b/custom_ui/services/stripe_service.py @@ -54,8 +54,8 @@ class StripeService: "company": company, "payment_type": "advance" if for_advance_payment else "full" }, - success_url=f"{get_url()}/payment-success?session_id={{CHECKOUT_SESSION_ID}}", - cancel_url=f"{get_url()}/payment-cancelled", + success_url=f"{get_url()}/payment_success?session_id={{CHECKOUT_SESSION_ID}}", + cancel_url=f"{get_url()}/payment_cancelled", ) return session diff --git a/custom_ui/www/cancelled_payment.html b/custom_ui/www/cancelled_payment.html deleted file mode 100644 index 8ada12e..0000000 --- a/custom_ui/www/cancelled_payment.html +++ /dev/null @@ -1,4 +0,0 @@ -{% extends "templates/web.html" %} -{% block page_content %} -

Payment cancelled.

-{% endblock %} diff --git a/custom_ui/www/payment_cancelled.html b/custom_ui/www/payment_cancelled.html new file mode 100644 index 0000000..4fbec21 --- /dev/null +++ b/custom_ui/www/payment_cancelled.html @@ -0,0 +1,141 @@ + + + + + + Payment Cancelled + + + + +
+
+

Payment Cancelled

+

Your payment has been cancelled.

+ +
+

Payment Not Processed

+

No charges have been made to your account. If you cancelled by mistake or need assistance, please try again or contact support.

+
+ +
+

What happens next?

+
    +
  • No payment has been processed
  • +
  • You can safely close this window
  • +
  • Try your payment again if needed
  • +
  • Contact us if you need help
  • +
+
+
+ + diff --git a/custom_ui/www/payment_cancelled.py b/custom_ui/www/payment_cancelled.py new file mode 100644 index 0000000..e69de29 diff --git a/custom_ui/www/payment_success.html b/custom_ui/www/payment_success.html new file mode 100644 index 0000000..f6daddb --- /dev/null +++ b/custom_ui/www/payment_success.html @@ -0,0 +1,212 @@ + + + + + + Payment Successful + + + + +
+
+ {% if reference_doc %} +

+ {% if company_doc and company_doc.company_name %} + {{ company_doc.company_name }} + {% else %} + Payment Received + {% endif %} +

+ {% if reference_doc.doctype == "Sales Order" %} +

+ {% if reference_doc.customer %} + Thank you {{ reference_doc.customer }} for your advance payment! + {% else %} + Thank you for your advance payment! + {% endif %} +

+
+

The remaining balance will be invoiced once the project is complete.

+
+ {% else %} +

+ {% if reference_doc.customer %} + Thank you {{ reference_doc.customer }} for your payment! + {% else %} + Thank you for your payment! + {% endif %} +

+ {% endif %} + + {% if company_doc %} +
+

Have Questions?

+

We're here to help! Contact us if you need assistance.

+
+ {% if company_doc.company_name %} +
+ Company: + {{ company_doc.company_name }} +
+ {% endif %} + + {% if company_doc.phone_no %} +
+ Phone: + {{ company_doc.phone_no }} +
+ {% endif %} + + {% if company_doc.email %} + + {% endif %} + + {% if company_doc.website %} +
+ Website: + {{ company_doc.website }} +
+ {% endif %} +
+
+ {% endif %} + {% else %} +

Payment Received

+

Thank you for your payment!

+ {% endif %} +
+ + diff --git a/custom_ui/www/payment_success.py b/custom_ui/www/payment_success.py new file mode 100644 index 0000000..8db1438 --- /dev/null +++ b/custom_ui/www/payment_success.py @@ -0,0 +1,18 @@ +import frappe + +def get_context(context): + context.no_cache = 1 + + context.title = "Payment Received" + context.message = "Thank you for your payment! Your transaction was successful." + + context.session_id = frappe.form_dict.get("session_id") + + payment_entry = frappe.get_value("Payment Entry", {"reference_no": context.session_id}, "name") + payment_entry_doc = frappe.get_doc("Payment Entry", payment_entry) if payment_entry else None + reference = payment_entry_doc.references[0] if payment_entry_doc and payment_entry_doc.references else None + reference_doc = frappe.get_doc(reference.reference_doctype, reference.reference_name) if reference else None + company_doc = frappe.get_doc("Company", reference_doc.company) if reference_doc and reference_doc.company else None + context.reference_doc = reference_doc.as_dict() if reference_doc else None + context.company_doc = company_doc.as_dict() if company_doc else None + return context \ No newline at end of file diff --git a/custom_ui/www/successful_payment.html b/custom_ui/www/successful_payment.html deleted file mode 100644 index a9e4113..0000000 --- a/custom_ui/www/successful_payment.html +++ /dev/null @@ -1,4 +0,0 @@ -{% extends "templates/web.html" %} -{% block page_content %} -

Thank you for your payment!

-{% endblock %} diff --git a/frontend/src/components/calendar/jobs/SNWProjectCalendar.vue b/frontend/src/components/calendar/jobs/SNWProjectCalendar.vue index 978ca0c..f339930 100644 --- a/frontend/src/components/calendar/jobs/SNWProjectCalendar.vue +++ b/frontend/src/components/calendar/jobs/SNWProjectCalendar.vue @@ -17,6 +17,12 @@ {{ weekDisplayText }} mdi-calendar + This Week @@ -991,13 +997,14 @@ const handleDrop = async (event, foremanId, date) => { await Api.updateServiceAppointmentScheduledDates( draggedService.value.name, date, - draggedService.value.expectedEndDate, // Keep the same end date + date, // Reset to single day when moved foreman.name ); // Update the scheduled job scheduledServices.value[scheduledIndex] = { ...scheduledServices.value[scheduledIndex], expectedStartDate: date, + expectedEndDate: date, // Reset to single day foreman: foreman.name }; notifications.addSuccess("Job moved successfully!"); @@ -1174,9 +1181,10 @@ const handleResize = (event) => { // Calculate proposed end date by adding days to the CURRENT end date let proposedEndDate = addDays(currentEndDate, daysToAdd); - // Don't allow shrinking before the current end date (minimum stay at current) - if (daysToAdd < 0) { - proposedEndDate = currentEndDate; + // Don't allow shrinking before the start date + const startDate = resizingJob.value.expectedStartDate; + if (parseLocalDate(proposedEndDate) < parseLocalDate(startDate)) { + proposedEndDate = startDate; } let newEndDate = proposedEndDate; @@ -1306,13 +1314,14 @@ const fetchServiceAppointments = async (currentDate) => { { "expectedStartDate": ["<=", endDate], "expectedEndDate": [">=", startDate], - "status": ["not in", ["Canceled"]] + "status": ["not in", ["Canceled", "Open"]] } ); unscheduledServices.value = await Api.getServiceAppointments( [companyStore.currentCompany], { - "status": "Open" + "status": "Open", + "ready_to_schedule": 1 } );