accounting workflows

This commit is contained in:
Thanakorn S
2026-05-20 10:17:02 +07:00
parent 04a683bd02
commit 7396db6ffc
199 changed files with 23539 additions and 5345 deletions
+8 -133
View File
@@ -1,91 +1,15 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
require '../../../assets/utils/classes/FileUploader.php';
require '../../../assets/utils/classes/CompanyProfileManager.php';
require_role($user_role, ['owner', 'admin']);
// ─── Allowed upload types ─────────────────────────────────────────────────
const ALLOWED_MIME = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
const ALLOWED_EXT = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
const MAX_SIZE = 2 * 1024 * 1024; // 2 MB
// ─── Helper: handle one image slot ────────────────────────────────────────
function handle_image_slot(
string $slot, // 'company_logo' | 'company_seal'
string $action, // 'keep' | 'replace' | 'remove'
string $current, // current filename from DB
string $upload_dir, // absolute path to uploads/company/
string $prefix // filename prefix 'logo_' | 'seal_'
): ?string {
// 'keep' → return current unchanged
if ($action === 'keep') return $current;
// 'remove' → delete file, return ''
if ($action === 'remove') {
if ($current && file_exists($upload_dir . $current)) {
unlink($upload_dir . $current);
}
return '';
}
// 'replace' → validate + save new file
if ($action === 'replace' && !empty($_FILES[$slot]['tmp_name'])) {
$file = $_FILES[$slot];
if ($file['error'] !== UPLOAD_ERR_OK) {
throw new RuntimeException("Upload error on {$slot}: code {$file['error']}.");
}
if ($file['size'] > MAX_SIZE) {
throw new RuntimeException('File too large. Maximum size is 2 MB.');
}
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $file['tmp_name']);
finfo_close($finfo);
if (!in_array($mime, ALLOWED_MIME, true)) {
throw new RuntimeException('Invalid file type. Only JPEG, PNG, GIF, WEBP allowed.');
}
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if (!in_array($ext, ALLOWED_EXT, true)) {
throw new RuntimeException('Invalid file extension. Only jpg, png, gif, webp allowed.');
}
// Delete old file first
if ($current && file_exists($upload_dir . $current)) {
unlink($upload_dir . $current);
}
$filename = $prefix . uniqid() . '.' . $ext;
if (!move_uploaded_file($file['tmp_name'], $upload_dir . $filename)) {
throw new RuntimeException("Failed to save {$slot}.");
}
return $filename;
}
return $current; // fallback
}
try {
$companyProfile = new CompanyProfileManager($pdo1, $company_id);
// ── Fetch current image filenames from DB ─────────────────────────────
$sth = $pdo1->prepare(
'SELECT company_logo, company_seal FROM company_list WHERE company_id = :id LIMIT 1'
);
$sth->execute([':id' => $company_id]);
db_check($sth, $answer);
$current = $sth->fetch(PDO::FETCH_ASSOC);
if (!$current) {
$answer['message'] = 'Company not found.';
http_response_code(404);
exit(json_encode($answer));
}
$current = $companyProfile->getProfile();
// ── Upload directory ──────────────────────────────────────────────────
$upload_dir = $include_url . 'uploads/company/';
@@ -97,60 +21,11 @@
$logo_action = $data['logo_action'] ?? 'keep';
$seal_action = $data['seal_action'] ?? 'keep';
$new_logo = handle_image_slot('company_logo', $logo_action, $current['company_logo'] ?? '', $upload_dir, 'logo_');
$new_seal = handle_image_slot('company_seal', $seal_action, $current['company_seal'] ?? '', $upload_dir, 'seal_');
$new_logo = $companyProfile->handleImageSlot('company_logo', $logo_action, $current['company_logo'] ?? '', $upload_dir, 'logo_');
$new_seal = $companyProfile->handleImageSlot('company_seal', $seal_action, $current['company_seal'] ?? '', $upload_dir, 'seal_');
// ── Text field sanitisation ───────────────────────────────────────────
$channel = strtolower(preg_replace('/[^a-z0-9\-_]/', '', $data['channel_name'] ?? ''));
// ── UPDATE company_list ───────────────────────────────────────────────
$sth = $pdo1->prepare("
UPDATE company_list SET
channel_name = :channel_name,
company_name = :company_name,
company_name2 = :company_name2,
company_logo = :company_logo,
company_seal = :company_seal,
branch = :branch,
branch_no = :branch_no,
fiscal_year = :fiscal_year,
fx = :fx,
address = :address,
address2 = :address2,
tax_id = :tax_id,
prompt_pay = :prompt_pay,
entrepreneur = :entrepreneur,
email = :email,
phone = :phone,
fax = :fax,
website = :website,
facebook_page = :facebook_page
WHERE company_id = :company_id
");
$sth->execute([
':channel_name' => $channel,
':company_name' => trim($data['company_name'] ?? ''),
':company_name2' => trim($data['company_name2'] ?? ''),
':company_logo' => $new_logo,
':company_seal' => $new_seal,
':branch' => trim($data['branch'] ?? 'สำนักงานใหญ่'),
':branch_no' => trim($data['branch_no'] ?? ''),
':fiscal_year' => trim($data['fiscal_year'] ?? ''),
':fx' => trim($data['fx'] ?? 'thb'),
':address' => trim($data['address'] ?? ''),
':address2' => trim($data['address2'] ?? ''),
':tax_id' => trim($data['tax_id'] ?? ''),
':prompt_pay' => trim($data['prompt_pay'] ?? ''),
':entrepreneur' => trim($data['entrepreneur'] ?? ''),
':email' => trim($data['email'] ?? ''),
':phone' => trim($data['phone'] ?? ''),
':fax' => trim($data['fax'] ?? ''),
':website' => trim($data['website'] ?? ''),
':facebook_page' => trim($data['facebook_page'] ?? ''),
':company_id' => $company_id,
]);
db_check($sth, $answer);
// ── Persist company profile ───────────────────────────────────────────
$companyProfile->saveProfile($data, $new_logo, $new_seal);
$answer['success'] = 1;
$answer['message'] = 'Company profile saved.';
@@ -168,4 +43,4 @@
}
exit(json_encode($answer));
?>
?>
+5 -28
View File
@@ -2,15 +2,13 @@
session_start();
require '../../../assets/utils/db_auth.php';
require '../../../assets/utils/classes/FileUploader.php';
require '../../../assets/utils/classes/UserManager.php';
try {
$um = new UserManager($pdo1, $company_id, $user_id);
// ── Fetch current picture filename from DB ────────────────
$sth = $pdo1->prepare(
'SELECT profile_picture FROM user WHERE user_id = :user_id LIMIT 1'
);
$sth->execute([':user_id' => $user_id]);
$current_picture = $sth->fetchColumn() ?: '';
$current_picture = $um->getProfilePicture();
// ── Handle new picture upload ─────────────────────────────
$db_picture = $current_picture;
@@ -36,28 +34,7 @@
}
// ── Update user record ────────────────────────────────────
$sth = $pdo1->prepare(
"UPDATE user SET
name = :name,
surname = :surname,
email = :email,
phone = :phone,
country = :country,
address = :address,
profile_picture = :profile_picture
WHERE user_id = :user_id"
);
$sth->execute([
':name' => trim($data['name'] ?? ''),
':surname' => trim($data['surname'] ?? ''),
':email' => trim($data['email'] ?? ''),
':phone' => trim($data['phone'] ?? ''),
':country' => trim($data['country'] ?? ''),
':address' => trim($data['address'] ?? ''),
':profile_picture' => $db_picture,
':user_id' => $user_id,
]);
db_check($sth, $answer);
$um->updateProfile($data, $db_picture);
// ── Refresh session ───────────────────────────────────────
$_SESSION['login_name'] = trim($data['name'] ?? '');
@@ -73,4 +50,4 @@
http_response_code(500);
}
exit(json_encode($answer));
exit(json_encode($answer));
+9 -117
View File
@@ -1,131 +1,23 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
require '../../../assets/utils/classes/SmtpManager.php';
require_role($user_role, ['owner', 'admin']);
// ─── Encrypt password — same method/key/iv as config.php ─────────────────
function encrypt_password(string $plain): string {
global $pinkey, $method, $iv;
return openssl_encrypt($plain, $method, $pinkey, 0, $iv);
}
try {
$server = trim($data['smtp_host'] ?? '');
$port = trim($data['smtp_port'] ?? '587');
$username = trim($data['smtp_username'] ?? '');
$raw_pass = $data['smtp_password'] ?? ''; // blank = keep current
$from_name = trim($data['smtp_from_name'] ?? '');
$from_email = trim($data['smtp_from_email'] ?? '');
$encryption = trim($data['smtp_encryption'] ?? 'tls');
if (!$server || !$username) {
$answer['message'] = 'SMTP host and username are required.';
http_response_code(422);
exit(json_encode($answer));
}
if (!in_array($port, ['25', '465', '587'], true)) $port = '587';
if (!in_array($encryption, ['tls', 'ssl', 'none'], true)) $encryption = 'tls';
// Check if row already exists (uses pdo1 — company_smtp lives in wms2)
$sth = $pdo1->prepare("
SELECT smtp_id FROM company_smtp
WHERE company_id = :company_id LIMIT 1
");
$sth->execute([':company_id' => $company_id]);
db_check($sth, $answer);
$existing_id = $sth->fetchColumn();
if ($existing_id) {
if ($raw_pass !== '') {
$sth = $pdo1->prepare("
UPDATE company_smtp SET
server = :server,
port = :port,
username = :username,
password = :password,
from_name = :from_name,
from_email = :from_email,
encryption = :encryption,
updated_at = NOW()
WHERE smtp_id = :smtp_id
");
$sth->execute([
':server' => $server,
':port' => $port,
':username' => $username,
':password' => encrypt_password($raw_pass),
':from_name' => $from_name,
':from_email' => $from_email,
':encryption' => $encryption,
':smtp_id' => $existing_id,
]);
} else {
// Keep existing password — don't touch it
$sth = $pdo1->prepare("
UPDATE company_smtp SET
server = :server,
port = :port,
username = :username,
from_name = :from_name,
from_email = :from_email,
encryption = :encryption,
updated_at = NOW()
WHERE smtp_id = :smtp_id
");
$sth->execute([
':server' => $server,
':port' => $port,
':username' => $username,
':from_name' => $from_name,
':from_email' => $from_email,
':encryption' => $encryption,
':smtp_id' => $existing_id,
]);
}
} else {
// New record — password required
if ($raw_pass === '') {
$answer['message'] = 'Password is required for a new SMTP configuration.';
http_response_code(422);
exit(json_encode($answer));
}
$sth = $pdo1->prepare("
INSERT INTO company_smtp
(company_id, server, port, username, password,
from_name, from_email, encryption, updated_at)
VALUES
(:company_id, :server, :port, :username, :password,
:from_name, :from_email, :encryption, NOW())
");
$sth->execute([
':company_id' => $company_id,
':server' => $server,
':port' => $port,
':username' => $username,
':password' => encrypt_password($raw_pass),
':from_name' => $from_name,
':from_email' => $from_email,
':encryption' => $encryption,
]);
}
db_check($sth, $answer);
$smtp = new SmtpManager($pdo1, $company_id, $method, $pinkey, $iv);
$smtp->save($data);
$answer['success'] = 1;
$answer['message'] = 'SMTP settings saved.';
} catch (Exception $e) {
$answer['message'] = 'Failed to save SMTP settings.';
http_response_code(500);
$answer['message'] = $e->getMessage();
http_response_code(in_array($e->getMessage(), [
'SMTP host and username are required.',
'Password is required for a new SMTP configuration.',
], true) ? 422 : 500);
}
exit(json_encode($answer));
?>
?>
+6 -31
View File
@@ -1,42 +1,17 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
require '../../../assets/utils/classes/CompanyProfileManager.php';
try {
$sth = $pdo1->prepare("
SELECT
company_id, channel_name,
company_name, company_name2,
company_logo, company_seal,
branch, branch_no,
fiscal_year, fx,
address, address2,
tax_id, prompt_pay, entrepreneur,
email, phone, fax,
website, facebook_page
FROM company_list
WHERE company_id = :company_id
LIMIT 1
");
$sth->execute([':company_id' => $company_id]);
db_check($sth, $answer);
$company = $sth->fetch(PDO::FETCH_ASSOC);
if (!$company) {
$answer['message'] = 'Company not found.';
http_response_code(404);
exit(json_encode($answer));
}
$company_profile = new CompanyProfileManager($pdo1, $company_id);
$answer['success'] = 1;
$answer['output'] = $company;
$answer['output'] = $company_profile->getProfile();
} catch (Exception $e) {
$answer['message'] = 'Failed to load company profile.';
http_response_code(500);
$answer['message'] = $e->getMessage();
http_response_code($e->getMessage() === 'Company not found.' ? 404 : 500);
}
exit(json_encode($answer));
?>
?>
+4 -20
View File
@@ -1,28 +1,12 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
require '../../../assets/utils/classes/SmtpManager.php';
try {
$sth = $pdo1->prepare("
SELECT
server,
port,
username,
from_name,
from_email,
encryption
FROM company_smtp
WHERE company_id = :company_id
LIMIT 1
");
$sth->execute([':company_id' => $company_id]);
db_check($sth, $answer);
$row = $sth->fetch(PDO::FETCH_ASSOC);
$smtp = new SmtpManager($pdo1, $company_id, $method, $pinkey, $iv);
$answer['success'] = 1;
$answer['output'] = $row ?: null; // null = not configured yet
$answer['output'] = $smtp->get();
} catch (Exception $e) {
$answer['message'] = $e->getMessage();
@@ -30,4 +14,4 @@
}
exit(json_encode($answer));
?>
?>
+2 -9
View File
@@ -10,10 +10,9 @@ require '../../../assets/utils/db_auth.php';
require '../../../assets/utils/classes/UserManager.php';
$action = $data['action'] ?? '';
$um = new UserManager($pdo1, $company_id, $user_id);
if ($action === 'read') {
$um = new UserManager($pdo1, $company_id, $user_id);
$answer['success'] = 1;
$answer['output'] = $um->getCompanyList();
$answer['current'] = (int)$_SESSION['login_company_id'];
@@ -29,13 +28,7 @@ if ($action === 'update') {
exit(json_encode($answer));
}
$sth = $pdo1->prepare(
"SELECT company_id, role FROM company_map_user
WHERE company_id = :company_id AND user_id = :user_id
LIMIT 1"
);
$sth->execute([':company_id' => $target_company_id, ':user_id' => $user_id]);
$target_map = $sth->fetch(PDO::FETCH_ASSOC);
$target_map = $um->getCompanyAccess($target_company_id);
if (!$target_map) {
$answer['message'] = 'You do not have access to this company.';
+10 -43
View File
@@ -1,57 +1,24 @@
<?php
session_start();
require '../../../assets/utils/db_auth.php';
require '../../../assets/utils/classes/SmtpManager.php';
require_role($user_role, ['owner', 'admin']);
try {
$to = trim($data['test_email'] ?? '');
if (!filter_var($to, FILTER_VALIDATE_EMAIL)) {
$answer['message'] = 'Invalid recipient email address.';
http_response_code(422);
exit(json_encode($answer));
}
// Fetch from_name / channel_name for the sender display
$sth = $pdo1->prepare("
SELECT from_name FROM company_smtp
WHERE company_id = :company_id LIMIT 1
");
$sth->execute([':company_id' => $company_id]);
db_check($sth, $answer);
$row = $sth->fetch(PDO::FETCH_ASSOC);
if (!$row) {
$answer['message'] = 'No SMTP configuration found. Please save your settings first.';
http_response_code(422);
exit(json_encode($answer));
}
$channel_name = $row['from_name'] ?: 'WMS System';
// Use existing mailer — it reads company_smtp via pdo1 automatically
require_once $include_url . 'assets/utils/module/mailer.php';
$mailer = new mailer(['pdo1' => $pdo1]);
$mailer->send_email([
'company_id' => $company_id,
'smtp' => [], // empty = mailer reads from company_smtp
'to' => $to,
'subject' => 'SMTP Test — WMS',
'message' => "This is a test email from your WMS SMTP configuration.\n\nIf you received this, your SMTP settings are working correctly.",
'channel_name' => $channel_name,
'key' => $pinkey,
]);
$smtp = new SmtpManager($pdo1, $company_id, $method, $pinkey, $iv);
$to = trim((string)($data['test_email'] ?? ''));
$smtp->sendTest($to);
$answer['success'] = 1;
$answer['message'] = 'Test email sent to ' . htmlspecialchars($to) . '.';
} catch (Exception $e) {
$answer['message'] = 'Failed to send test email: ' . $e->getMessage();
http_response_code(500);
$answer['message'] = $e->getMessage();
http_response_code(in_array($e->getMessage(), [
'Invalid recipient email address.',
'No SMTP configuration found. Please save your settings first.',
], true) ? 422 : 500);
}
exit(json_encode($answer));
?>
?>