diff --git a/client_asset_bulk_assign_contact_modal.php b/client_asset_bulk_assign_contact_modal.php
new file mode 100644
index 00000000..c95978cd
--- /dev/null
+++ b/client_asset_bulk_assign_contact_modal.php
@@ -0,0 +1,44 @@
+
+
+
+
+
Bulk Assign Contact
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client_asset_bulk_assign_location_modal.php b/client_asset_bulk_assign_location_modal.php
new file mode 100644
index 00000000..c9989c2f
--- /dev/null
+++ b/client_asset_bulk_assign_location_modal.php
@@ -0,0 +1,43 @@
+
+
+
+
+
Bulk Assign Location
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client_asset_bulk_edit_status_modal.php b/client_asset_bulk_edit_status_modal.php
new file mode 100644
index 00000000..bc3ddbe1
--- /dev/null
+++ b/client_asset_bulk_edit_status_modal.php
@@ -0,0 +1,36 @@
+
+
+
+
+
Bulk Edit Status
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client_asset_copy_modal.php b/client_asset_copy_modal.php
index 10ea9946..bf676a8f 100644
--- a/client_asset_copy_modal.php
+++ b/client_asset_copy_modal.php
@@ -132,7 +132,7 @@
'$asset_created_at' OR network_archived_at IS NULL) AND network_client_id = $client_id ORDER BY network_name ASC");
+ $sql_networks = mysqli_query($mysqli, "SELECT * FROM networks WHERE network_archived_at IS NULL AND network_client_id = $client_id ORDER BY network_name ASC");
while ($row = mysqli_fetch_array($sql_networks)) {
$network_id_select = intval($row['network_id']);
$network_name_select = nullable_htmlentities($row['network_name']);
@@ -215,7 +215,7 @@
- Vendor -
'$asset_created_at' OR vendor_archived_at IS NULL) AND vendor_client_id = $client_id AND vendor_template = 0 ORDER BY vendor_name ASC");
+ $sql_vendors = mysqli_query($mysqli, "SELECT * FROM vendors WHERE vendor_archived_at IS NULL AND vendor_client_id = $client_id AND vendor_template = 0 ORDER BY vendor_name ASC");
while ($row = mysqli_fetch_array($sql_vendors)) {
$vendor_id_select = intval($row['vendor_id']);
$vendor_name_select = nullable_htmlentities($row['vendor_name']);
@@ -341,7 +341,7 @@
diff --git a/client_contact_bulk_assign_location_modal.php b/client_contact_bulk_assign_location_modal.php
new file mode 100644
index 00000000..404a545a
--- /dev/null
+++ b/client_contact_bulk_assign_location_modal.php
@@ -0,0 +1,43 @@
+
+
+
+
+
Bulk Assign Location
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client_contact_bulk_edit_department_modal.php b/client_contact_bulk_edit_department_modal.php
new file mode 100644
index 00000000..ae6192cb
--- /dev/null
+++ b/client_contact_bulk_edit_department_modal.php
@@ -0,0 +1,31 @@
+
+
+
+
+
Bulk Set Department / Group
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client_contact_bulk_edit_phone_modal.php b/client_contact_bulk_edit_phone_modal.php
new file mode 100644
index 00000000..cc27c317
--- /dev/null
+++ b/client_contact_bulk_edit_phone_modal.php
@@ -0,0 +1,31 @@
+
+
+
+
+
Bulk Set Phone Number
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client_contact_bulk_edit_role_modal.php b/client_contact_bulk_edit_role_modal.php
new file mode 100644
index 00000000..f5b59899
--- /dev/null
+++ b/client_contact_bulk_edit_role_modal.php
@@ -0,0 +1,49 @@
+
+
+
+
+
Bulk Set Roles
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Important Person and pins them to the top of the contact list
+
+
+
+
+
+
+
+ Receives Invoices and Receipts and has access to billing via the portal
+
+
+
+
+
+
+
+ Person to contact for technical related things and has access to all tickets and documents via the portal
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client_contact_details.php b/client_contact_details.php
index 863b94d8..6eeaffd6 100644
--- a/client_contact_details.php
+++ b/client_contact_details.php
@@ -84,33 +84,33 @@ if (isset($_GET['contact_id'])) {
-
Up to 20 files can be uploaded at once by holding down CTRL and selecting files
diff --git a/client_files.php b/client_files.php
index 196a11e6..86231d60 100644
--- a/client_files.php
+++ b/client_files.php
@@ -157,9 +157,21 @@ $num_of_files = mysqli_num_rows($sql);
Ticket: $ticket_prefix$ticket_number Subject: $ticket_subject Status: Open Portal: https://$config_base_url/portal/ticket.php?id=$id
~ $company_name Support Department $config_ticket_from_email $company_phone");
+ $email_subject = "Ticket created - [$ticket_prefix$ticket_number] - $ticket_subject (scheduled)";
+ $email_body = "##- Please type your reply above this line -##
Hello $contact_name,
A ticket regarding \"$ticket_subject\" has been automatically created for you.
Ticket: $ticket_prefix$ticket_number Subject: $ticket_subject Status: Open Portal: https://$config_base_url/portal/ticket.php?id=$id
-- $company_name - Support $config_ticket_from_email $company_phone";
$email = [
'from' => $config_ticket_from_email,
@@ -316,8 +313,8 @@ if (mysqli_num_rows($sql_scheduled_tickets) > 0) {
// Notify agent's via the DL address of the new ticket, if it's populated with a valid email
if (filter_var($config_ticket_new_ticket_notification_email, FILTER_VALIDATE_EMAIL)) {
- $email_subject = mysqli_real_escape_string($mysqli, "ITFlow - New Scheduled Ticket - $client_name: $ticket_subject");
- $email_body = mysqli_real_escape_string($mysqli, "Hello,
This is a notification that a new scheduled ticket has been raised in ITFlow. Ticket: $ticket_prefix$ticket_number Client: $client_name Priority: $priority Link: https://$config_base_url/ticket.php?ticket_id=$id
This is a notification that a new scheduled ticket has been raised in ITFlow. Ticket: $ticket_prefix$ticket_number Client: $client_name Priority: $priority Link: https://$config_base_url/ticket.php?ticket_id=$id
--------------------------------
$ticket_subject $ticket_details";
$email = [
'from' => $config_ticket_from_email,
@@ -420,8 +417,8 @@ if ($config_ticket_autoclose == 1) {
$ticket_reply_row = mysqli_fetch_array($sql_ticket_reply);
$ticket_reply = $ticket_reply_row['ticket_reply'];
- $subject = mysqli_real_escape_string($mysqli, "Ticket pending closure - [$ticket_prefix$ticket_number] - $ticket_subject");
- $body = mysqli_real_escape_string($mysqli, "##- Please type your reply above this line -##
Hello, $contact_name
This is an automatic friendly reminder that your ticket regarding $ticket_subject will be closed, unless you respond.
If your issue is resolved, you can ignore this email - the ticket will automatically close. If you need further assistance, please respond to this email.
~ $company_name Support Department $config_ticket_from_email $company_phone");
+ $subject = "Ticket pending closure - [$ticket_prefix$ticket_number] - $ticket_subject";
+ $body = "##- Please type your reply above this line -##
Hello, $contact_name
This is an automatic friendly reminder that your ticket regarding $ticket_subject will be closed, unless you respond.
If your issue is resolved, you can ignore this email - the ticket will automatically close. If you need further assistance, please respond to this email.
-- $company_name - Support $config_ticket_from_email $company_phone";
$data = [
[
@@ -501,10 +498,10 @@ if ($config_send_invoice_reminders == 1) {
mysqli_query($mysqli, "INSERT INTO notifications SET notification_type = 'Invoice Overdue', notification = 'Invoice $invoice_prefix$invoice_number for $client_name in the amount of $invoice_amount is overdue by $day days', notification_action = 'invoice.php?invoice_id=$invoice_id', notification_client_id = $client_id, notification_entity_id = $invoice_id");
- $subject = mysqli_real_escape_string($mysqli, "Overdue Invoice $invoice_prefix$invoice_number");
- $body = mysqli_real_escape_string($mysqli, "Hello $contact_name,
Our records indicate that we have not yet received payment for the invoice $invoice_prefix$invoice_number. We kindly request that you submit your payment as soon as possible. If you have any questions or concerns, please do not hesitate to contact us at $company_phone.
+ $subject = "Overdue Invoice $invoice_prefix$invoice_number";
+ $body = "Hello $contact_name,
Our records indicate that we have not yet received payment for the invoice $invoice_prefix$invoice_number. We kindly request that you submit your payment as soon as possible. If you have any questions or concerns, please do not hesitate to contact us at $company_phone.
- Kindly review the invoice details mentioned below.
-- $company_name - Billing $config_invoice_from_email $company_phone";
$mail = addToMailQueue($mysqli, [
[
@@ -732,6 +729,10 @@ if ($config_telemetry > 0 OR $config_telemetry = 2) {
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('recurring_id') AS num FROM tickets"));
$ticket_count = $row['num'];
+ // Scheduled Ticket Count
+ $row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('scheduled_ticket_id') AS num FROM scheduled_tickets"));
+ $scheduled_ticket_count = $row['num'];
+
// Calendar Event Count
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('event_id') AS num FROM events"));
$calendar_event_count = $row['num'];
@@ -896,6 +897,7 @@ if ($config_telemetry > 0 OR $config_telemetry = 2) {
'currency' => "$company_currency",
'client_count' => $client_count,
'ticket_count' => $ticket_count,
+ 'scheduled_ticket_count' => $scheduled_ticket_count,
'calendar_event_count' => $calendar_event_count,
'quote_count' => $quote_count,
'invoice_count' => $invoice_count,
@@ -961,8 +963,6 @@ if ($config_telemetry > 0 OR $config_telemetry = 2) {
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Cron', log_action = 'Telemetry', log_description = 'Cron sent telemetry results to ITFlow Developers'");
}
-
-
/*
* ###############################################################################################################
* FINISH UP
diff --git a/cron_mail_queue.php b/cron_mail_queue.php
index 63497247..0827c092 100644
--- a/cron_mail_queue.php
+++ b/cron_mail_queue.php
@@ -1,16 +1,8 @@
set('URI.AllowedSchemes', ['data' => true, 'src' => true, 'http' => true, 'https' => true]);
-$purifier = new HTMLPurifier($purifier_config);
-
$sql_settings = mysqli_query($mysqli, "SELECT * FROM settings WHERE company_id = 1");
$row = mysqli_fetch_array($sql_settings);
@@ -61,21 +53,27 @@ file_put_contents($lock_file_path, "Locked");
// Process Mail Queue
-// Get Mail Queue that hasnt been sent yet
-// Email Status: 0 Queued, 1 Sending, 2 Failed, 3 Sent
-$sql_queue = mysqli_query($mysqli, "SELECT * FROM email_queue WHERE email_status = 0");
+// Email Status:
+// 0 Queued
+// 1 Sending
+// 2 Failed
+// 3 Sent
+
+// Get Mail Queue that has status of Queued and send it to the function sendSingleEmail() located in functions.php
+
+$sql_queue = mysqli_query($mysqli, "SELECT * FROM email_queue WHERE email_status = 0 AND email_queued_at <= NOW()");
if (mysqli_num_rows($sql_queue) > 0) {
while ($row = mysqli_fetch_array($sql_queue)) {
$email_id = intval($row['email_id']);
- $email_from = nullable_htmlentities($row['email_from']);
- $email_from_name = nullable_htmlentities($row['email_from_name']);
- $email_recipient = nullable_htmlentities($row['email_recipient']);
- $email_recipient_name = nullable_htmlentities($row['email_recipient_name']);
- $email_subject = $purifier->purify($row['email_subject']);
- $email_content = $purifier->purify($row['email_content']);
- $email_queued_at = nullable_htmlentities($row['email_queued_at']);
- $email_sent_at = nullable_htmlentities($row['email_sent_at']);
+ $email_from = $row['email_from'];
+ $email_from_name = $row['email_from_name'];
+ $email_recipient = $row['email_recipient'];
+ $email_recipient_name = $row['email_recipient_name'];
+ $email_subject = $row['email_subject'];
+ $email_content = $row['email_content'];
+ $email_queued_at = $row['email_queued_at'];
+ $email_sent_at = $row['email_sent_at'];
// Sanitized Input
$email_recipient_logging = sanitizeInput($row['email_recipient']);
@@ -115,23 +113,22 @@ if (mysqli_num_rows($sql_queue) > 0) {
}
}
-// Process Failed Mail up to 4 times every 30 mins
+//
-// Get Mail Queue that hasnt been sent yet
-// Email Status: 0 Queued, 1 Sending, 2 Failed, 3 Sent
+// Get Mail that failed to send and attempt to send Failed Mail up to 4 times every 30 mins
$sql_failed_queue = mysqli_query($mysqli, "SELECT * FROM email_queue WHERE email_status = 2 AND email_attempts < 4 AND email_failed_at < NOW() + INTERVAL 30 MINUTE");
if (mysqli_num_rows($sql_failed_queue) > 0) {
while ($row = mysqli_fetch_array($sql_failed_queue)) {
$email_id = intval($row['email_id']);
- $email_from = nullable_htmlentities($row['email_from']);
- $email_from_name = nullable_htmlentities($row['email_from_name']);
- $email_recipient = nullable_htmlentities($row['email_recipient']);
- $email_recipient_name = nullable_htmlentities($row['email_recipient_name']);
- $email_subject = $purifier->purify($row['email_subject']);
- $email_content = $purifier->purify($row['email_content']);
- $email_queued_at = nullable_htmlentities($row['email_queued_at']);
- $email_sent_at = nullable_htmlentities($row['email_sent_at']);
+ $email_from = $row['email_from'];
+ $email_from_name = $row['email_from_name'];
+ $email_recipient = $row['email_recipient'];
+ $email_recipient_name = $row['email_recipient_name'];
+ $email_subject = $row['email_subject'];
+ $email_content = $row['email_content'];
+ $email_queued_at = $row['email_queued_at'];
+ $email_sent_at = $row['email_sent_at'];
// Increment the attempts
$email_attempts = intval($row['email_attempts']) + 1;
@@ -173,5 +170,5 @@ if (mysqli_num_rows($sql_failed_queue) > 0) {
}
}
-// Remove the lock file
+// Remove the lock file once mail has finished processing so it doesnt get overun causing possible duplicates
unlink($lock_file_path);
diff --git a/cron_ticket_email_parser.php b/cron_ticket_email_parser.php
index 2bfceb8c..b168e405 100644
--- a/cron_ticket_email_parser.php
+++ b/cron_ticket_email_parser.php
@@ -23,12 +23,14 @@ require_once "functions.php";
// Get settings for the "default" company
require_once "get_settings.php";
+$config_ticket_prefix = sanitizeInput($config_ticket_prefix);
+$config_ticket_from_name = sanitizeInput($config_ticket_from_name);
// Get company name & phone
$sql = mysqli_query($mysqli, "SELECT company_name, company_phone FROM companies WHERE company_id = 1");
$row = mysqli_fetch_array($sql);
$company_name = sanitizeInput($row['company_name']);
-$company_phone = formatPhoneNumber($row['company_phone']);
+$company_phone = sanitizeInput(formatPhoneNumber($row['company_phone']));
// Check setting enabled
if ($config_ticket_email_parse == 0) {
@@ -161,8 +163,8 @@ function addTicket($contact_id, $contact_name, $contact_email, $client_id, $date
// E-mail client notification that ticket has been created
if ($config_ticket_client_general_notifications == 1) {
- $subject_email = mysqli_escape_string($mysqli, "Ticket created - [$config_ticket_prefix$ticket_number] - $subject");
- $body = mysqli_escape_string($mysqli, "##- Please type your reply above this line -##
Hello, $contact_name
Thank you for your email. A ticket regarding \"$subject\" has been automatically created for you.
Ticket: $config_ticket_prefix$ticket_number Subject: $subject Status: Open https://$config_base_url/portal/ticket.php?id=$id
~ $company_name Support Department $config_ticket_from_email $company_phone");
+ $subject_email = "Ticket created - [$config_ticket_prefix$ticket_number] - $subject";
+ $body = "##- Please type your reply above this line -##
Hello $contact_name,
Thank you for your email. A ticket regarding \"$subject\" has been automatically created for you.
Ticket: $config_ticket_prefix$ticket_number Subject: $subject Status: Open https://$config_base_url/portal/ticket.php?id=$id
This is a notification that a new ticket has been raised in ITFlow. Client: $client_name Priority: Low (email parsed) Link: https://$config_base_url/ticket.php?ticket_id=$id
--------------------------------
$subject $details";
$data[] = [
@@ -238,7 +240,7 @@ function addReply($from_email, $date, $subject, $ticket_number, $message, $attac
mysqli_query($mysqli, "INSERT INTO notifications SET notification_type = 'Ticket', notification = 'Email parser: $from_email attempted to re-open ticket $config_ticket_prefix$ticket_number (ID $ticket_id) - check inbox manually to see email', notification_action = 'ticket.php?ticket_id=$ticket_id', notification_client_id = $client_id");
$email_subject = "Action required: This ticket is already closed";
- $email_body = "Hi there,
You've tried to reply to a ticket that is closed - we won't see your response.
Please raise a new ticket by sending a fresh e-mail to our support address.
~ $company_name Support Department $config_ticket_from_email $company_phone";
+ $email_body = "Hi there,
You\'ve tried to reply to a ticket that is closed - we won\'t see your response.
Please raise a new ticket by sending a fresh e-mail to our support address below.
-- $company_name - Support $config_ticket_from_email $company_phone";
$data = [
[
@@ -253,7 +255,7 @@ function addReply($from_email, $date, $subject, $ticket_number, $message, $attac
addToMailQueue($mysqli, $data);
- return false;
+ return true;
}
// Check WHO replied (was it the owner of the ticket or someone else on CC?)
@@ -327,11 +329,11 @@ function addReply($from_email, $date, $subject, $ticket_number, $message, $attac
// Get tech details
$tech_sql = mysqli_query($mysqli, "SELECT user_email, user_name FROM users WHERE user_id = $ticket_assigned_to LIMIT 1");
$tech_row = mysqli_fetch_array($tech_sql);
- $tech_email = santizeInput($tech_row['user_email']);
+ $tech_email = sanitizeInput($tech_row['user_email']);
$tech_name = sanitizeInput($tech_row['user_name']);
- $subject = mysqli_escape_string($mysqli, "Ticket updated - [$config_ticket_prefix$ticket_number] - $subject");
- $body = mysqli_escape_string($mysqli, "##- Please type your reply above this line -##
Hello, $tech_name
A new reply has been added to the ticket \"$subject\".
Ticket: $config_ticket_prefix$ticket_number Subject: $subject Status: Open https://$config_base_url/portal/ticket.php?id=$ticket_id
~ $company_name Support Department $config_ticket_from_email $company_phone");
+ $subject = "Ticket updated - [$config_ticket_prefix$ticket_number] - $subject";
+ $body = "##- Please type your reply above this line -##
Hello $tech_name,
A new reply has been added to the ticket \"$subject\".
Ticket: $config_ticket_prefix$ticket_number Subject: $subject Status: Open https://$config_base_url/portal/ticket.php?id=$ticket_id
-- $company_name - Support $config_ticket_from_email $company_phone";
$data = [
[
@@ -363,7 +365,7 @@ function addReply($from_email, $date, $subject, $ticket_number, $message, $attac
return false;
}
}
-// End Add Reply Function
+// END ADD REPLY FUNCTION -------------------------------------------------
// Prepare connection string with encryption (TLS/SSL/)
$imap_mailbox = "$config_imap_host:$config_imap_port/imap/$config_imap_encryption";
@@ -515,6 +517,7 @@ if ($emails) {
imap_setflag_full($imap, $email, "\\Seen");
imap_mail_move($imap, $email, $imap_folder);
} else {
+ // Basically just flags all emails keep them unread and it doesnt move closed tickets
echo "Failed to process email - flagging for manual review.";
imap_setflag_full($imap, $email, "\\Flagged");
}
diff --git a/database_updates.php b/database_updates.php
index 01bc7589..eab18b02 100644
--- a/database_updates.php
+++ b/database_updates.php
@@ -1560,10 +1560,15 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
}
+
if (CURRENT_DATABASE_VERSION == '1.0.2') {
//Insert queries here required to update to DB version 1.0.3
- mysqli_query($mysqli, "ALTER TABLE `tickets` ADD `ticket_schedule` DATETIME DEFAULT NULL AFTER `ticket_billable`");
-
+ mysqli_query($mysqli, "ALTER TABLE `settings` ADD `config_stripe_expense_vendor` INT(11) NOT NULL DEFAULT 0 AFTER `config_stripe_account`");
+ mysqli_query($mysqli, "ALTER TABLE `settings` ADD `config_stripe_expense_category` INT(11) NOT NULL DEFAULT 0 AFTER `config_stripe_expense_vendor`");
+ mysqli_query($mysqli, "ALTER TABLE `settings` ADD `config_stripe_percentage_fee` DECIMAL(4,4) NOT NULL DEFAULT 0.029 AFTER `config_stripe_expense_category`");
+ mysqli_query($mysqli, "ALTER TABLE `settings` ADD `config_stripe_flat_fee` DECIMAL(15,2) NOT NULL DEFAULT 0.30 AFTER `config_stripe_percentage_fee`");
+ mysqli_query($mysqli, "ALTER TABLE `settings` CHANGE `config_stripe_account` `config_stripe_account` INT(11) NOT NULL DEFAULT 0");
+
//Then, update the database to the next sequential version
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.0.3'");
}
@@ -1572,10 +1577,12 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
// Please add this same comment block to the bottom of this file, and update the version number.
// Uncomment Below Lines, to add additional database updates
//
- // if (CURRENT_DATABASE_VERSION == '1.0.3') {
- // // Insert queries here required to update to DB version 1.0.4
+
+ if (CURRENT_DATABASE_VERSION == '1.0.3') {
+ //Insert queries here required to update to DB version 1.0.4
+ mysqli_query($mysqli, "ALTER TABLE `tickets` ADD `ticket_schedule` DATETIME DEFAULT NULL AFTER `ticket_billable`");
// // Then, update the database to the next sequential version
- // mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.0.4'");
+ mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.0.4'");
// }
} else {
diff --git a/db.sql b/db.sql
index 3b449279..a64c5fd4 100644
--- a/db.sql
+++ b/db.sql
@@ -1270,7 +1270,11 @@ CREATE TABLE `settings` (
`config_stripe_enable` tinyint(1) NOT NULL DEFAULT 0,
`config_stripe_publishable` varchar(255) DEFAULT NULL,
`config_stripe_secret` varchar(255) DEFAULT NULL,
- `config_stripe_account` tinyint(1) NOT NULL DEFAULT 0,
+ `config_stripe_account` int(11) NOT NULL DEFAULT 0,
+ `config_stripe_expense_vendor` int(11) NOT NULL DEFAULT 0,
+ `config_stripe_expense_category` int(11) NOT NULL DEFAULT 0,
+ `config_stripe_percentage_fee` decimal(4,4) NOT NULL DEFAULT 0.0290,
+ `config_stripe_flat_fee` decimal(15,2) NOT NULL DEFAULT 0.30,
`config_stripe_client_pays_fees` tinyint(1) NOT NULL DEFAULT 0,
`config_azure_client_id` varchar(200) DEFAULT NULL,
`config_azure_client_secret` varchar(200) DEFAULT NULL,
@@ -1757,4 +1761,4 @@ CREATE TABLE `vendors` (
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
--- Dump completed on 2024-01-15 13:07:46
+-- Dump completed on 2024-01-27 23:58:10
diff --git a/expense_bulk_edit_account_modal.php b/expense_bulk_edit_account_modal.php
new file mode 100644
index 00000000..43c930b7
--- /dev/null
+++ b/expense_bulk_edit_account_modal.php
@@ -0,0 +1,58 @@
+
+
+
+
+
Bulk Set Account
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/expense_bulk_edit_category_modal.php b/expense_bulk_edit_category_modal.php
new file mode 100644
index 00000000..e0e79da7
--- /dev/null
+++ b/expense_bulk_edit_category_modal.php
@@ -0,0 +1,42 @@
+
+
+
+
+
Bulk Set Category
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/expense_bulk_edit_client_modal.php b/expense_bulk_edit_client_modal.php
new file mode 100644
index 00000000..2d069289
--- /dev/null
+++ b/expense_bulk_edit_client_modal.php
@@ -0,0 +1,43 @@
+
There was an error verifying your payment. Please contact us for more information.
");
// Setup Stripe
-$stripe_vars = mysqli_fetch_array(mysqli_query($mysqli, "SELECT config_stripe_enable, config_stripe_publishable, config_stripe_secret, config_stripe_account FROM settings WHERE company_id = 1"));
+$stripe_vars = mysqli_fetch_array(mysqli_query($mysqli, "SELECT config_stripe_enable, config_stripe_publishable, config_stripe_secret, config_stripe_account, config_stripe_expense_vendor, config_stripe_expense_category, config_stripe_percentage_fee, config_stripe_flat_fee, config_stripe_client_pays_fees FROM settings WHERE company_id = 1"));
$config_stripe_enable = intval($stripe_vars['config_stripe_enable']);
$config_stripe_publishable = nullable_htmlentities($stripe_vars['config_stripe_publishable']);
$config_stripe_secret = nullable_htmlentities($stripe_vars['config_stripe_secret']);
$config_stripe_account = intval($stripe_vars['config_stripe_account']);
+$config_stripe_expense_vendor = intval($stripe_vars['config_stripe_expense_vendor']);
+$config_stripe_expense_category = intval($stripe_vars['config_stripe_expense_category']);
+$config_stripe_percentage_fee = floatval($stripe_vars['config_stripe_percentage_fee']);
+$config_stripe_flat_fee = floatval($stripe_vars['config_stripe_flat_fee']);
+$config_stripe_client_pays_fees = intval($stripe_vars['config_stripe_client_pays_fees']);
// Check Stripe is configured
if ($config_stripe_enable == 0 || $config_stripe_account == 0 || empty($config_stripe_publishable) || empty($config_stripe_secret)) {
@@ -75,26 +78,19 @@ if (isset($_GET['invoice_id'], $_GET['url_key']) && !isset($_GET['payment_intent
$row = mysqli_fetch_array($sql);
$company_locale = nullable_htmlentities($row['company_locale']);
- $config_stripe_client_pays_fees = intval(getSettingValue($mysqli, 'config_stripe_client_pays_fees'));
-
// Add up all the payments for the invoice and get the total amount paid to the invoice
$sql_amount_paid = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS amount_paid FROM payments WHERE payment_invoice_id = $invoice_id");
$row = mysqli_fetch_array($sql_amount_paid);
$amount_paid = floatval($row['amount_paid']);
$balance_to_pay = $invoice_amount - $amount_paid;
- // Check config to see if client pays fees is enabled
if ($config_stripe_client_pays_fees == 1) {
- $balance_before_fees = $balance_to_pay;
- $percentage_fee = 0.029;
- $flat_fee = 0.30;
- // Calculate the amount to charge the client
- $balance_to_pay = ($balance_to_pay + $flat_fee) / (1 - $percentage_fee);
- // Calculate the fee amount
- $gateway_fee = round($balance_to_pay - $balance_before_fees, 2);
+ $balance_before_fees = $balance_to_pay;
+ // Calculate the Gateway fee
+ $gateway_fee = round($balance_to_pay * $config_stripe_percentage_fee + $config_stripe_flat_fee, 2);
+ $balance_to_pay = $balance_to_pay + $gateway_fee;
+ }
- }
-
//Round balance to pay to 2 decimal places
$balance_to_pay = round($balance_to_pay, 2);
@@ -252,25 +248,22 @@ if (isset($_GET['invoice_id'], $_GET['url_key']) && !isset($_GET['payment_intent
// Invoice exists - get details
$row = mysqli_fetch_array($invoice_sql);
$invoice_id = intval($row['invoice_id']);
- $invoice_prefix = nullable_htmlentities($row['invoice_prefix']);
+ $invoice_prefix = sanitizeInput($row['invoice_prefix']);
$invoice_number = intval($row['invoice_number']);
$invoice_amount = floatval($row['invoice_amount']);
- $invoice_currency_code = nullable_htmlentities($row['invoice_currency_code']);
- $invoice_url_key = nullable_htmlentities($row['invoice_url_key']);
+ $invoice_currency_code = sanitizeInput($row['invoice_currency_code']);
+ $invoice_url_key = sanitizeInput($row['invoice_url_key']);
$client_id = intval($row['client_id']);
- $client_name = nullable_htmlentities($row['client_name']);
- $contact_name = $row['contact_name'];
- $contact_email = $row['contact_email'];
+ $client_name = sanitizeInput($row['client_name']);
+ $contact_name = sanitizeInput($row['contact_name']);
+ $contact_email = sanitizeInput($row['contact_email']);
$sql_company = mysqli_query($mysqli, "SELECT * FROM companies WHERE company_id = 1");
$row = mysqli_fetch_array($sql_company);
- $company_name = mysqli_real_escape_string($mysqli, nullable_htmlentities($row['company_name']));
- $company_phone = nullable_htmlentities($row['company_phone']);
- $company_locale = nullable_htmlentities($row['company_locale']);
-
- $config_stripe_client_pays_fees = intval(getSettingValue($mysqli, 'config_stripe_client_pays_fees'));
-
+ $company_name = sanitizeInput($row['company_name']);
+ $company_phone = sanitizeInput(formatPhoneNumber($row['company_phone']));
+ $company_locale = sanitizeInput($row['company_locale']);
// Set Currency Formatting
$currency_format = numfmt_create($company_locale, NumberFormatter::CURRENCY);
@@ -281,12 +274,21 @@ if (isset($_GET['invoice_id'], $_GET['url_key']) && !isset($_GET['payment_intent
$amount_paid_previously = $row['amount_paid'];
$balance_to_pay = $invoice_amount - $amount_paid_previously;
- // Check config to see if client pays fees is enabled
+ // Check config to see if client pays fees is enabled or if should expense it
if ($config_stripe_client_pays_fees == 1) {
- $percentage_fee = 0.029;
- $flat_fee = 0.30;
+ // Calculate gateway expense fee
+ $gateway_fee = round($balance_to_pay * $config_stripe_percentage_fee + $config_stripe_flat_fee, 2);
// Calculate the amount to charge the client
- $balance_to_pay = ($balance_to_pay + $flat_fee) / (1 - $percentage_fee);
+ $balance_to_pay = $balance_to_pay + $gateway_fee;
+ }
+
+ // Check to see if Expense Fields are configured and client pays fee is off then create expense
+ if ($config_stripe_client_pays_fees == 0 && $config_stripe_expense_vendor > 0 && $config_stripe_expense_category > 0) {
+ // Calculate gateway expense fee
+ $gateway_fee = round($balance_to_pay * $config_stripe_percentage_fee + $config_stripe_flat_fee, 2);
+
+ // Add Expense
+ mysqli_query($mysqli,"INSERT INTO expenses SET expense_date = '$pi_date', expense_amount = $gateway_fee, expense_currency_code = '$invoice_currency_code', expense_account_id = $config_stripe_account, expense_vendor_id = $config_stripe_expense_vendor, expense_client_id = $client_id, expense_category_id = $config_stripe_expense_category, expense_description = 'Stripe Transaction for Invoice $invoice_prefix$invoice_number In the Amount of $balance_to_pay', expense_reference = 'Stripe - $pi_id'");
}
// Round balance to pay to 2 decimal places
@@ -335,14 +337,14 @@ if (isset($_GET['invoice_id'], $_GET['url_key']) && !isset($_GET['payment_intent
$config_smtp_encryption = $row['config_smtp_encryption'];
$config_smtp_username = $row['config_smtp_username'];
$config_smtp_password = $row['config_smtp_password'];
- $config_mail_from_email = $row['config_mail_from_email'];
- $config_mail_from_name = $row['config_mail_from_name'];
- $config_invoice_from_name = $row['config_invoice_from_name'];
- $config_invoice_from_email = $row['config_invoice_from_email'];
+ $config_invoice_from_name = sanitizeInput($row['config_invoice_from_name']);
+ $config_invoice_from_email = sanitizeInput($row['config_invoice_from_email']);
+
+ $config_base_url = sanitizeInput($config_base_url);
if (!empty($config_smtp_host)) {
$subject = "Payment Received - Invoice $invoice_prefix$invoice_number";
- $body = "Hello $contact_name,
We have received your payment in the amount of " . $pi_currency . $pi_amount_paid . " for invoice $invoice_prefix$invoice_number. Please keep this email as a receipt for your records.
We have received your payment in the amount of " . $pi_currency . $pi_amount_paid . " for invoice $invoice_prefix$invoice_number. Please keep this email as a receipt for your records.