346 lines
9.9 KiB
PHP
346 lines
9.9 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
use Carbon\Carbon;
|
||
|
|
use Illuminate\Mail\MailManager;
|
||
|
|
use Illuminate\Support\Facades\Auth;
|
||
|
|
use Illuminate\Support\Facades\DB;
|
||
|
|
use Illuminate\Support\Facades\Schema;
|
||
|
|
use Illuminate\Support\Facades\Session;
|
||
|
|
use Illuminate\Support\Facades\Storage;
|
||
|
|
use Modules\Authentication\Models\Setting;
|
||
|
|
use Modules\Authentication\Models\SubscriptionItem;
|
||
|
|
use Modules\Authentication\Models\User;
|
||
|
|
use Modules\HRM\Models\Attendance;
|
||
|
|
use Modules\HRM\Models\AttendanceLog;
|
||
|
|
use Modules\Restaurant\Models\FoodVariant;
|
||
|
|
|
||
|
|
if (! function_exists('_lang')) {
|
||
|
|
function _lang($string = '')
|
||
|
|
{
|
||
|
|
$targetLang = ! empty(Session::get('locale'))
|
||
|
|
? Session::get('locale')
|
||
|
|
: (! empty(get_option('language')) ? get_option('language') : 'en');
|
||
|
|
|
||
|
|
$json = [];
|
||
|
|
if (file_exists(lang_path()."/$targetLang.json")) {
|
||
|
|
$json = json_decode(file_get_contents(lang_path()."/$targetLang.json"), true);
|
||
|
|
}
|
||
|
|
|
||
|
|
return ! empty($json[$string]) ? $json[$string] : $string;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (! function_exists('get_option')) {
|
||
|
|
function get_option($name)
|
||
|
|
{
|
||
|
|
try {
|
||
|
|
// Check if the database connection is valid
|
||
|
|
DB::connection()->getPdo();
|
||
|
|
|
||
|
|
$setting = DB::table('settings')->where('option_key', $name)->get();
|
||
|
|
if (! $setting->isEmpty()) {
|
||
|
|
return $setting[0]->option_value;
|
||
|
|
}
|
||
|
|
} catch (\Exception $e) {
|
||
|
|
// If database connection fails, return an empty string or log the error
|
||
|
|
return '';
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (! function_exists('get_saas_option')) {
|
||
|
|
function get_saas_option(string $name, $default = '')
|
||
|
|
{
|
||
|
|
try {
|
||
|
|
// Check DB connection
|
||
|
|
DB::connection()->getPdo();
|
||
|
|
|
||
|
|
// Ensure table exists
|
||
|
|
if (! Schema::hasTable('s_a_a_s_settings')) {
|
||
|
|
return $default;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Fetch setting
|
||
|
|
$setting = DB::table('s_a_a_s_settings')
|
||
|
|
->where('name', $name)
|
||
|
|
->first();
|
||
|
|
|
||
|
|
return $setting ? $setting->value : $default;
|
||
|
|
} catch (\Throwable $e) {
|
||
|
|
return $default;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (! function_exists('setEnvValue')) {
|
||
|
|
function setEnvValue(string $key, string $value): void
|
||
|
|
{
|
||
|
|
$envPath = base_path('.env');
|
||
|
|
|
||
|
|
if (! file_exists($envPath)) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
$escapedValue = '"'.trim(str_replace('"', '\"', $value)).'"';
|
||
|
|
$envContent = file_get_contents($envPath);
|
||
|
|
|
||
|
|
if (preg_match("/^{$key}=.*/m", $envContent)) {
|
||
|
|
$envContent = preg_replace(
|
||
|
|
"/^{$key}=.*/m",
|
||
|
|
"{$key}={$escapedValue}",
|
||
|
|
$envContent
|
||
|
|
);
|
||
|
|
} else {
|
||
|
|
$envContent .= PHP_EOL."{$key}={$escapedValue}";
|
||
|
|
}
|
||
|
|
|
||
|
|
file_put_contents($envPath, $envContent);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (! function_exists('fileUploader')) {
|
||
|
|
function fileUploader(string $dir, string $format, $image = null, $oldImage = null)
|
||
|
|
{
|
||
|
|
if ($image == null) {
|
||
|
|
return $oldImage ?? 'def.png';
|
||
|
|
}
|
||
|
|
|
||
|
|
// Delete old image(s) if exist
|
||
|
|
if (! empty($oldImage)) {
|
||
|
|
if (is_array($oldImage)) {
|
||
|
|
foreach ($oldImage as $file) {
|
||
|
|
Storage::disk('public')->delete($dir.$file);
|
||
|
|
}
|
||
|
|
} elseif (is_string($oldImage)) {
|
||
|
|
Storage::disk('public')->delete($dir.$oldImage);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Generate unique file name
|
||
|
|
$imageName = Carbon::now()->toDateString().'-'.uniqid().'.'.$format;
|
||
|
|
|
||
|
|
// Ensure directory exists
|
||
|
|
if (! Storage::disk('public')->exists($dir)) {
|
||
|
|
Storage::disk('public')->makeDirectory($dir);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Store the uploaded file
|
||
|
|
if ($image instanceof \Illuminate\Http\UploadedFile) {
|
||
|
|
$image->storeAs($dir, $imageName, 'public');
|
||
|
|
} else {
|
||
|
|
throw new \Exception('Invalid file type provided for upload.');
|
||
|
|
}
|
||
|
|
|
||
|
|
return $imageName;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (! function_exists('fileRemover')) {
|
||
|
|
function fileRemover(string $dir, $image)
|
||
|
|
{
|
||
|
|
if (! isset($image)) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (Storage::disk('public')->exists($dir.$image)) {
|
||
|
|
Storage::disk('public')->delete($dir.$image);
|
||
|
|
}
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (! function_exists('restaurantUniqueRule')) {
|
||
|
|
function restaurantUniqueRule(string $table, string $column = 'name', ?int $restaurantId = null, ?int $ignoreId = null, string $restaurantColumn = 'restaurant_id')
|
||
|
|
{
|
||
|
|
$restaurantId = $restaurantId ?? auth()->user()->restaurant_id;
|
||
|
|
|
||
|
|
$rule = \Illuminate\Validation\Rule::unique($table, $column)
|
||
|
|
->where($restaurantColumn, $restaurantId);
|
||
|
|
|
||
|
|
if ($ignoreId) {
|
||
|
|
$rule->ignore($ignoreId);
|
||
|
|
}
|
||
|
|
|
||
|
|
return $rule;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (! function_exists('restaurantUniqueRule')) {
|
||
|
|
function getDefaultVariant($foodId)
|
||
|
|
{
|
||
|
|
return FoodVariant::where('food_item_id', $foodId)->where('is_default', true)->first();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (! function_exists('getUserRestaurantId')) {
|
||
|
|
function getUserRestaurantId()
|
||
|
|
{
|
||
|
|
$user = auth()->user();
|
||
|
|
if (! $user) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
return (int) $user->restaurant_id;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (! function_exists('getUserId')) {
|
||
|
|
function getUserId()
|
||
|
|
{
|
||
|
|
$user = auth()->user();
|
||
|
|
if (! $user) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
return (int) $user->id;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (! function_exists('authUser')) {
|
||
|
|
function authUser(): User
|
||
|
|
{
|
||
|
|
$authUser = auth()->user();
|
||
|
|
|
||
|
|
return $authUser;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (! function_exists('updateAttendanceSummary')) {
|
||
|
|
function updateAttendanceSummary($employeeId, $date)
|
||
|
|
{
|
||
|
|
$attendance = Attendance::firstOrCreate([
|
||
|
|
'employee_id' => $employeeId,
|
||
|
|
'date' => $date,
|
||
|
|
]);
|
||
|
|
|
||
|
|
$logs = AttendanceLog::where('employee_id', $employeeId)
|
||
|
|
->whereDate('punch_time', $date)
|
||
|
|
->orderBy('punch_time')
|
||
|
|
->get();
|
||
|
|
|
||
|
|
if ($logs->isEmpty()) {
|
||
|
|
$attendance->update([
|
||
|
|
'first_clock_in' => null,
|
||
|
|
'last_clock_out' => null,
|
||
|
|
'hours_worked' => 0,
|
||
|
|
]);
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
$firstIn = $logs->where('type', 'in')->first()?->punch_time;
|
||
|
|
$lastOut = $logs->where('type', 'out')->last()?->punch_time;
|
||
|
|
|
||
|
|
$totalSeconds = 0;
|
||
|
|
$stack = [];
|
||
|
|
foreach ($logs as $log) {
|
||
|
|
if ($log->type === 'in') {
|
||
|
|
$stack[] = $log->punch_time;
|
||
|
|
} elseif ($log->type === 'out' && ! empty($stack)) {
|
||
|
|
$in = array_pop($stack);
|
||
|
|
$out = $log->punch_time;
|
||
|
|
$totalSeconds += Carbon::parse($out)->diffInSeconds(Carbon::parse($in));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
$hoursWorked = round($totalSeconds / 3600, 2);
|
||
|
|
|
||
|
|
$attendance->update([
|
||
|
|
'first_clock_in' => $firstIn ? Carbon::parse($firstIn)->format('H:i:s') : null,
|
||
|
|
'last_clock_out' => $lastOut ? Carbon::parse($lastOut)->format('H:i:s') : null,
|
||
|
|
'hours_worked' => $hoursWorked,
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (! function_exists('checkPackageAccess')) {
|
||
|
|
function checkPackageAccess()
|
||
|
|
{
|
||
|
|
$subscription = SubscriptionItem::where(['user_id' => Auth::user()->id, 'restaurant_id' => GetUserRestaurantId()])
|
||
|
|
->with('package')->latest('id')
|
||
|
|
->first();
|
||
|
|
|
||
|
|
return $subscription->package?->name;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (! function_exists('get_setting')) {
|
||
|
|
function get_setting($key, $restaurantId = null, $type = 'vendor', $default = null)
|
||
|
|
{
|
||
|
|
$query = Setting::query();
|
||
|
|
if ($restaurantId) {
|
||
|
|
$query->where('restaurant_id', $restaurantId);
|
||
|
|
}
|
||
|
|
|
||
|
|
if ($type) {
|
||
|
|
$query->where('type', $type);
|
||
|
|
}
|
||
|
|
|
||
|
|
$setting = $query->where('key', $key)->first();
|
||
|
|
|
||
|
|
return $setting ? $setting->value : $default;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (! function_exists('shop_mailer_send')) {
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Send email via shop SMTP dynamically
|
||
|
|
*
|
||
|
|
* @param \Illuminate\Mail\Mailable $mailable
|
||
|
|
*/
|
||
|
|
function shop_mailer_send(int $restaurantId, string $toEmail, $mailable): array
|
||
|
|
{
|
||
|
|
// 1. Check if default contact method is email
|
||
|
|
// $defaultMethod = get_setting('default_contact_method', $restaurantId);
|
||
|
|
// if ($defaultMethod !== 'email') {
|
||
|
|
// return [
|
||
|
|
// 'status' => false,
|
||
|
|
// 'message' => 'Default contact method is not email.',
|
||
|
|
// ];
|
||
|
|
// }
|
||
|
|
|
||
|
|
// 2. Get SMTP settings from database
|
||
|
|
$smtp = [
|
||
|
|
'transport' => 'smtp',
|
||
|
|
'host' => get_setting('email_smtp_host', $restaurantId),
|
||
|
|
'port' => get_setting('email_smtp_port', $restaurantId),
|
||
|
|
'encryption' => get_setting('email_smtp_encryption', $restaurantId) ?? 'tls',
|
||
|
|
'username' => get_setting('email_smtp_username', $restaurantId),
|
||
|
|
'password' => get_setting('email_smtp_password', $restaurantId),
|
||
|
|
'timeout' => null,
|
||
|
|
'local_domain' => parse_url(env('APP_URL', 'http://localhost'), PHP_URL_HOST),
|
||
|
|
];
|
||
|
|
|
||
|
|
// 3. Ensure all required credentials exist
|
||
|
|
if (empty($smtp['host']) || empty($smtp['port']) || empty($smtp['username']) || empty($smtp['password'])) {
|
||
|
|
return [
|
||
|
|
'status' => false,
|
||
|
|
'message' => 'SMTP configuration incomplete for this shop.',
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
try {
|
||
|
|
// 4. Dynamically set mailer config
|
||
|
|
config()->set('mail.mailers.dynamic', $smtp);
|
||
|
|
|
||
|
|
// 5. Get dynamic mailer instance
|
||
|
|
$mailer = app(MailManager::class)->mailer('dynamic');
|
||
|
|
|
||
|
|
// 6. Send email
|
||
|
|
$mailer->to($toEmail)->send($mailable);
|
||
|
|
|
||
|
|
return [
|
||
|
|
'status' => true,
|
||
|
|
'message' => 'Email sent successfully.',
|
||
|
|
];
|
||
|
|
} catch (Exception $e) {
|
||
|
|
return [
|
||
|
|
'status' => false,
|
||
|
|
'message' => 'Failed to send email: '.$e->getMessage(),
|
||
|
|
];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|