Compare commits
32
Commits
db4c8cf40f
...
1602bdd72e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1602bdd72e | ||
|
|
14357ade4d | ||
|
|
0237b1dc2a | ||
|
|
ce06aa9fac | ||
|
|
13a7e804af | ||
|
|
d1a83c9b09 | ||
|
|
3410ab85fe | ||
|
|
fac5df8cc3 | ||
|
|
21ee6e951a | ||
|
|
f02f801b31 | ||
|
|
a137ffe852 | ||
|
|
856038c762 | ||
|
|
5d58e35275 | ||
|
|
16fe344eef | ||
|
|
4375fc729f | ||
|
|
37a116437e | ||
|
|
56b5cb91b0 | ||
|
|
ce79962289 | ||
|
|
5aeeb87b21 | ||
|
|
744968120a | ||
|
|
8c0b214a9d | ||
|
|
279d2761e3 | ||
|
|
20bdb82ef9 | ||
|
|
66e38cfe52 | ||
|
|
8105d1cb6a | ||
|
|
84a628277d | ||
|
|
45a370ed91 | ||
|
|
0756b1de79 | ||
|
|
cf2b61f964 | ||
|
|
449fb0bf91 | ||
|
|
ee8bd29bd6 | ||
|
|
01c21d12b9 |
+1
-1
@@ -26,7 +26,6 @@ yarn-error.log
|
||||
/.nova
|
||||
/.vscode
|
||||
/.zed
|
||||
package-lock.json
|
||||
composer.lock
|
||||
/provision/
|
||||
/storage/logs/
|
||||
@@ -39,3 +38,4 @@ composer.lock
|
||||
/storage/framework/
|
||||
/storage/debugbar/
|
||||
/phpunit.dusk.xml
|
||||
/sonarqube-issues.csv
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<caption class="sr-only">Data table</caption>
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Metric</th>
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<caption class="sr-only">Data table</caption>
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>When</th>
|
||||
|
||||
@@ -63,9 +63,7 @@ class AuditTrailServiceProvider extends ServiceProvider
|
||||
$commandPath = __DIR__ . '/../Console';
|
||||
$commands = collect(File::allFiles($commandPath))
|
||||
->map(function ($file) {
|
||||
$class = 'Modules\\' . $this->moduleName . '\\Console\\' . $file->getFilenameWithoutExtension();
|
||||
|
||||
return $class;
|
||||
return 'Modules\\' . $this->moduleName . '\\Console\\' . $file->getFilenameWithoutExtension();
|
||||
})
|
||||
->filter(function ($class) {
|
||||
return class_exists($class);
|
||||
|
||||
@@ -14,18 +14,6 @@ class RouteServiceProvider extends ServiceProvider
|
||||
*/
|
||||
protected $moduleNamespace = 'Modules\AuditTrail\Http\Controllers';
|
||||
|
||||
/**
|
||||
* Called before routes are registered.
|
||||
*
|
||||
* Register any model bindings or pattern based filters.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
parent::boot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the routes for the application.
|
||||
*
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<caption class="sr-only">Data table</caption>
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Carrier</th>
|
||||
|
||||
@@ -26,40 +26,37 @@ class DeleteOpenAiFilesCommand extends Command
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
$service = new OpenAiFileService((string) $setting->api_key);
|
||||
|
||||
try {
|
||||
if ((bool) $this->option('dry-run')) {
|
||||
$files = $service->listFiles();
|
||||
|
||||
$this->info('Found ' . count($files) . ' OpenAI API file(s).');
|
||||
|
||||
foreach ($files as $file) {
|
||||
$this->line(sprintf(
|
||||
'- %s %s',
|
||||
(string) ($file['id'] ?? 'unknown'),
|
||||
(string) ($file['filename'] ?? 'unnamed'),
|
||||
));
|
||||
}
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
$result = $service->deleteAllFiles();
|
||||
|
||||
$this->info("Listed: {$result['listed']}");
|
||||
$this->info("Deleted: {$result['deleted']}");
|
||||
$this->info("Failed: {$result['failed']}");
|
||||
|
||||
foreach ($result['failures'] as $failure) {
|
||||
$this->error($failure['file_id'] . ': ' . $failure['error']);
|
||||
}
|
||||
|
||||
return $result['failed'] === 0 ? self::SUCCESS : self::FAILURE;
|
||||
return $this->executeFor(new OpenAiFileService((string) $setting->api_key));
|
||||
} catch (Throwable $exception) {
|
||||
$this->error($exception->getMessage());
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
private function executeFor(OpenAiFileService $service): int
|
||||
{
|
||||
if ((bool) $this->option('dry-run')) {
|
||||
$files = $service->listFiles();
|
||||
$this->info('Found ' . count($files) . ' OpenAI API file(s).');
|
||||
|
||||
foreach ($files as $file) {
|
||||
$this->line(sprintf('- %s %s', (string) ($file['id'] ?? 'unknown'), (string) ($file['filename'] ?? 'unnamed')));
|
||||
}
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
$result = $service->deleteAllFiles();
|
||||
$this->info("Listed: {$result['listed']}");
|
||||
$this->info("Deleted: {$result['deleted']}");
|
||||
$this->info("Failed: {$result['failed']}");
|
||||
|
||||
foreach ($result['failures'] as $failure) {
|
||||
$this->error($failure['file_id'] . ': ' . $failure['error']);
|
||||
}
|
||||
|
||||
return $result['failed'] === 0 ? self::SUCCESS : self::FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,5 @@ class ChatGPTDatabaseSeeder extends Seeder
|
||||
{
|
||||
Model::unguard();
|
||||
|
||||
// $this->call("OthersTableSeeder");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\ChatGPT\Exceptions;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
final class OpenAiFileException extends RuntimeException {}
|
||||
@@ -79,9 +79,7 @@ class ChatGPTServiceProvider extends ServiceProvider
|
||||
$commandPath = __DIR__ . '/../Console';
|
||||
$commands = collect(File::allFiles($commandPath))
|
||||
->map(function ($file) {
|
||||
$class = 'Modules\\' . $this->moduleName . '\\Console\\' . $file->getFilenameWithoutExtension();
|
||||
|
||||
return $class;
|
||||
return 'Modules\\' . $this->moduleName . '\\Console\\' . $file->getFilenameWithoutExtension();
|
||||
})
|
||||
->filter(function ($class) {
|
||||
return class_exists($class);
|
||||
|
||||
@@ -14,18 +14,6 @@ class RouteServiceProvider extends ServiceProvider
|
||||
*/
|
||||
protected $moduleNamespace = 'Modules\ChatGPT\Http\Controllers';
|
||||
|
||||
/**
|
||||
* Called before routes are registered.
|
||||
*
|
||||
* Register any model bindings or pattern based filters.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
parent::boot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the routes for the application.
|
||||
*
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
|
||||
<div class="mt-5 overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-slate-200 text-sm">
|
||||
<caption class="sr-only">Data table</caption>
|
||||
<thead class="bg-slate-50 text-left text-xs font-semibold uppercase tracking-wide text-slate-500">
|
||||
<tr>
|
||||
<th class="px-4 py-3">Name</th>
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Modules\ChatGPT\Services;
|
||||
|
||||
use Illuminate\Http\Client\PendingRequest;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use RuntimeException;
|
||||
use Modules\ChatGPT\Exceptions\OpenAiFileException;
|
||||
|
||||
class OpenAiFileService
|
||||
{
|
||||
@@ -33,7 +33,7 @@ class OpenAiFileService
|
||||
->get(self::BASE_URL . '/files', $query);
|
||||
|
||||
if ($response->failed()) {
|
||||
throw new RuntimeException('OpenAI file list request failed: ' . $response->body());
|
||||
throw new OpenAiFileException('OpenAI file list request failed: ' . $response->body());
|
||||
}
|
||||
|
||||
$payload = $response->json();
|
||||
@@ -63,7 +63,7 @@ class OpenAiFileService
|
||||
->delete(self::BASE_URL . '/files/' . rawurlencode($fileId));
|
||||
|
||||
if ($response->failed()) {
|
||||
throw new RuntimeException("OpenAI file delete request failed for {$fileId}: " . $response->body());
|
||||
throw new OpenAiFileException("OpenAI file delete request failed for {$fileId}: " . $response->body());
|
||||
}
|
||||
|
||||
return $response->json() ?? [];
|
||||
@@ -90,7 +90,7 @@ class OpenAiFileService
|
||||
try {
|
||||
$this->deleteFile($fileId);
|
||||
$deleted++;
|
||||
} catch (RuntimeException $exception) {
|
||||
} catch (OpenAiFileException $exception) {
|
||||
$failures[] = [
|
||||
'file_id' => $fileId,
|
||||
'error' => $exception->getMessage(),
|
||||
|
||||
@@ -11,6 +11,8 @@ use Modules\Warehouse\app\Models\Warehouse;
|
||||
|
||||
class CompanyAddressController extends Controller
|
||||
{
|
||||
private const MAX_STRING = 'max:255';
|
||||
|
||||
public function updateCompany(Request $request, Company $company)
|
||||
{
|
||||
$this->upsertAddress($request, $company);
|
||||
@@ -40,12 +42,12 @@ class CompanyAddressController extends Controller
|
||||
{
|
||||
$data = $request->validate([
|
||||
'label' => ['nullable', 'string', 'max:80'],
|
||||
'attention' => ['nullable', 'string', 'max:255'],
|
||||
'line_1' => ['required', 'string', 'max:255'],
|
||||
'line_2' => ['nullable', 'string', 'max:255'],
|
||||
'line_3' => ['nullable', 'string', 'max:255'],
|
||||
'locality' => ['required', 'string', 'max:255'],
|
||||
'administrative_area' => ['nullable', 'string', 'max:255'],
|
||||
'attention' => ['nullable', 'string', self::MAX_STRING],
|
||||
'line_1' => ['required', 'string', self::MAX_STRING],
|
||||
'line_2' => ['nullable', 'string', self::MAX_STRING],
|
||||
'line_3' => ['nullable', 'string', self::MAX_STRING],
|
||||
'locality' => ['required', 'string', self::MAX_STRING],
|
||||
'administrative_area' => ['nullable', 'string', self::MAX_STRING],
|
||||
'postal_code' => ['nullable', 'string', 'max:32'],
|
||||
'country_id' => ['required', Rule::exists('countries', 'id')->where('is_active', true)],
|
||||
'country_subdivision_id' => ['nullable', 'exists:country_subdivisions,id'],
|
||||
|
||||
@@ -45,7 +45,7 @@ class CompanyController extends Controller
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$company = Company::create($this->validated($request));
|
||||
Company::create($this->validated($request));
|
||||
|
||||
return redirect()
|
||||
->route('platform.companies.index')
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
|
||||
<div class="overflow-x-auto rounded-2xl bg-white shadow-sm ring-1 ring-zinc-200 dark:bg-zinc-900 dark:ring-zinc-800">
|
||||
<table class="min-w-full text-sm">
|
||||
<caption class="sr-only">Data table</caption>
|
||||
<thead>
|
||||
<tr class="border-b border-zinc-200 dark:border-zinc-800">
|
||||
<th class="p-4 text-left">Name</th>
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<caption class="sr-only">Data table</caption>
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Setting</th>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,257 +11,12 @@ class IsoCountriesSeeder extends Seeder
|
||||
public function run(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
$countries = [
|
||||
['alpha2' => 'AD', 'alpha3' => 'AND', 'numeric' => '020', 'name' => 'Andorra', 'official_name' => 'Principality of Andorra', 'common_name' => null, 'flag_emoji' => '🇦🇩'],
|
||||
['alpha2' => 'AE', 'alpha3' => 'ARE', 'numeric' => '784', 'name' => 'United Arab Emirates', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇦🇪'],
|
||||
['alpha2' => 'AF', 'alpha3' => 'AFG', 'numeric' => '004', 'name' => 'Afghanistan', 'official_name' => 'Islamic Republic of Afghanistan', 'common_name' => null, 'flag_emoji' => '🇦🇫'],
|
||||
['alpha2' => 'AG', 'alpha3' => 'ATG', 'numeric' => '028', 'name' => 'Antigua and Barbuda', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇦🇬'],
|
||||
['alpha2' => 'AI', 'alpha3' => 'AIA', 'numeric' => '660', 'name' => 'Anguilla', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇦🇮'],
|
||||
['alpha2' => 'AL', 'alpha3' => 'ALB', 'numeric' => '008', 'name' => 'Albania', 'official_name' => 'Republic of Albania', 'common_name' => null, 'flag_emoji' => '🇦🇱'],
|
||||
['alpha2' => 'AM', 'alpha3' => 'ARM', 'numeric' => '051', 'name' => 'Armenia', 'official_name' => 'Republic of Armenia', 'common_name' => null, 'flag_emoji' => '🇦🇲'],
|
||||
['alpha2' => 'AO', 'alpha3' => 'AGO', 'numeric' => '024', 'name' => 'Angola', 'official_name' => 'Republic of Angola', 'common_name' => null, 'flag_emoji' => '🇦🇴'],
|
||||
['alpha2' => 'AQ', 'alpha3' => 'ATA', 'numeric' => '010', 'name' => 'Antarctica', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇦🇶'],
|
||||
['alpha2' => 'AR', 'alpha3' => 'ARG', 'numeric' => '032', 'name' => 'Argentina', 'official_name' => 'Argentine Republic', 'common_name' => null, 'flag_emoji' => '🇦🇷'],
|
||||
['alpha2' => 'AS', 'alpha3' => 'ASM', 'numeric' => '016', 'name' => 'American Samoa', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇦🇸'],
|
||||
['alpha2' => 'AT', 'alpha3' => 'AUT', 'numeric' => '040', 'name' => 'Austria', 'official_name' => 'Republic of Austria', 'common_name' => null, 'flag_emoji' => '🇦🇹'],
|
||||
['alpha2' => 'AU', 'alpha3' => 'AUS', 'numeric' => '036', 'name' => 'Australia', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇦🇺'],
|
||||
['alpha2' => 'AW', 'alpha3' => 'ABW', 'numeric' => '533', 'name' => 'Aruba', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇦🇼'],
|
||||
['alpha2' => 'AX', 'alpha3' => 'ALA', 'numeric' => '248', 'name' => 'Åland Islands', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇦🇽'],
|
||||
['alpha2' => 'AZ', 'alpha3' => 'AZE', 'numeric' => '031', 'name' => 'Azerbaijan', 'official_name' => 'Republic of Azerbaijan', 'common_name' => null, 'flag_emoji' => '🇦🇿'],
|
||||
['alpha2' => 'BA', 'alpha3' => 'BIH', 'numeric' => '070', 'name' => 'Bosnia and Herzegovina', 'official_name' => 'Republic of Bosnia and Herzegovina', 'common_name' => null, 'flag_emoji' => '🇧🇦'],
|
||||
['alpha2' => 'BB', 'alpha3' => 'BRB', 'numeric' => '052', 'name' => 'Barbados', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇧🇧'],
|
||||
['alpha2' => 'BD', 'alpha3' => 'BGD', 'numeric' => '050', 'name' => 'Bangladesh', 'official_name' => 'People\'s Republic of Bangladesh', 'common_name' => null, 'flag_emoji' => '🇧🇩'],
|
||||
['alpha2' => 'BE', 'alpha3' => 'BEL', 'numeric' => '056', 'name' => 'Belgium', 'official_name' => 'Kingdom of Belgium', 'common_name' => null, 'flag_emoji' => '🇧🇪'],
|
||||
['alpha2' => 'BF', 'alpha3' => 'BFA', 'numeric' => '854', 'name' => 'Burkina Faso', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇧🇫'],
|
||||
['alpha2' => 'BG', 'alpha3' => 'BGR', 'numeric' => '100', 'name' => 'Bulgaria', 'official_name' => 'Republic of Bulgaria', 'common_name' => null, 'flag_emoji' => '🇧🇬'],
|
||||
['alpha2' => 'BH', 'alpha3' => 'BHR', 'numeric' => '048', 'name' => 'Bahrain', 'official_name' => 'Kingdom of Bahrain', 'common_name' => null, 'flag_emoji' => '🇧🇭'],
|
||||
['alpha2' => 'BI', 'alpha3' => 'BDI', 'numeric' => '108', 'name' => 'Burundi', 'official_name' => 'Republic of Burundi', 'common_name' => null, 'flag_emoji' => '🇧🇮'],
|
||||
['alpha2' => 'BJ', 'alpha3' => 'BEN', 'numeric' => '204', 'name' => 'Benin', 'official_name' => 'Republic of Benin', 'common_name' => null, 'flag_emoji' => '🇧🇯'],
|
||||
['alpha2' => 'BL', 'alpha3' => 'BLM', 'numeric' => '652', 'name' => 'Saint Barthélemy', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇧🇱'],
|
||||
['alpha2' => 'BM', 'alpha3' => 'BMU', 'numeric' => '060', 'name' => 'Bermuda', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇧🇲'],
|
||||
['alpha2' => 'BN', 'alpha3' => 'BRN', 'numeric' => '096', 'name' => 'Brunei Darussalam', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇧🇳'],
|
||||
['alpha2' => 'BO', 'alpha3' => 'BOL', 'numeric' => '068', 'name' => 'Bolivia, Plurinational State of', 'official_name' => 'Plurinational State of Bolivia', 'common_name' => 'Bolivia', 'flag_emoji' => '🇧🇴'],
|
||||
['alpha2' => 'BQ', 'alpha3' => 'BES', 'numeric' => '535', 'name' => 'Bonaire, Sint Eustatius and Saba', 'official_name' => 'Bonaire, Sint Eustatius and Saba', 'common_name' => null, 'flag_emoji' => '🇧🇶'],
|
||||
['alpha2' => 'BR', 'alpha3' => 'BRA', 'numeric' => '076', 'name' => 'Brazil', 'official_name' => 'Federative Republic of Brazil', 'common_name' => null, 'flag_emoji' => '🇧🇷'],
|
||||
['alpha2' => 'BS', 'alpha3' => 'BHS', 'numeric' => '044', 'name' => 'Bahamas', 'official_name' => 'Commonwealth of the Bahamas', 'common_name' => null, 'flag_emoji' => '🇧🇸'],
|
||||
['alpha2' => 'BT', 'alpha3' => 'BTN', 'numeric' => '064', 'name' => 'Bhutan', 'official_name' => 'Kingdom of Bhutan', 'common_name' => null, 'flag_emoji' => '🇧🇹'],
|
||||
['alpha2' => 'BV', 'alpha3' => 'BVT', 'numeric' => '074', 'name' => 'Bouvet Island', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇧🇻'],
|
||||
['alpha2' => 'BW', 'alpha3' => 'BWA', 'numeric' => '072', 'name' => 'Botswana', 'official_name' => 'Republic of Botswana', 'common_name' => null, 'flag_emoji' => '🇧🇼'],
|
||||
['alpha2' => 'BY', 'alpha3' => 'BLR', 'numeric' => '112', 'name' => 'Belarus', 'official_name' => 'Republic of Belarus', 'common_name' => null, 'flag_emoji' => '🇧🇾'],
|
||||
['alpha2' => 'BZ', 'alpha3' => 'BLZ', 'numeric' => '084', 'name' => 'Belize', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇧🇿'],
|
||||
['alpha2' => 'CA', 'alpha3' => 'CAN', 'numeric' => '124', 'name' => 'Canada', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇨🇦'],
|
||||
['alpha2' => 'CC', 'alpha3' => 'CCK', 'numeric' => '166', 'name' => 'Cocos (Keeling) Islands', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇨🇨'],
|
||||
['alpha2' => 'CD', 'alpha3' => 'COD', 'numeric' => '180', 'name' => 'Congo, The Democratic Republic of the', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇨🇩'],
|
||||
['alpha2' => 'CF', 'alpha3' => 'CAF', 'numeric' => '140', 'name' => 'Central African Republic', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇨🇫'],
|
||||
['alpha2' => 'CG', 'alpha3' => 'COG', 'numeric' => '178', 'name' => 'Congo', 'official_name' => 'Republic of the Congo', 'common_name' => null, 'flag_emoji' => '🇨🇬'],
|
||||
['alpha2' => 'CH', 'alpha3' => 'CHE', 'numeric' => '756', 'name' => 'Switzerland', 'official_name' => 'Swiss Confederation', 'common_name' => null, 'flag_emoji' => '🇨🇭'],
|
||||
['alpha2' => 'CI', 'alpha3' => 'CIV', 'numeric' => '384', 'name' => 'Côte d\'Ivoire', 'official_name' => 'Republic of Côte d\'Ivoire', 'common_name' => null, 'flag_emoji' => '🇨🇮'],
|
||||
['alpha2' => 'CK', 'alpha3' => 'COK', 'numeric' => '184', 'name' => 'Cook Islands', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇨🇰'],
|
||||
['alpha2' => 'CL', 'alpha3' => 'CHL', 'numeric' => '152', 'name' => 'Chile', 'official_name' => 'Republic of Chile', 'common_name' => null, 'flag_emoji' => '🇨🇱'],
|
||||
['alpha2' => 'CM', 'alpha3' => 'CMR', 'numeric' => '120', 'name' => 'Cameroon', 'official_name' => 'Republic of Cameroon', 'common_name' => null, 'flag_emoji' => '🇨🇲'],
|
||||
['alpha2' => 'CN', 'alpha3' => 'CHN', 'numeric' => '156', 'name' => 'China', 'official_name' => 'People\'s Republic of China', 'common_name' => null, 'flag_emoji' => '🇨🇳'],
|
||||
['alpha2' => 'CO', 'alpha3' => 'COL', 'numeric' => '170', 'name' => 'Colombia', 'official_name' => 'Republic of Colombia', 'common_name' => null, 'flag_emoji' => '🇨🇴'],
|
||||
['alpha2' => 'CR', 'alpha3' => 'CRI', 'numeric' => '188', 'name' => 'Costa Rica', 'official_name' => 'Republic of Costa Rica', 'common_name' => null, 'flag_emoji' => '🇨🇷'],
|
||||
['alpha2' => 'CU', 'alpha3' => 'CUB', 'numeric' => '192', 'name' => 'Cuba', 'official_name' => 'Republic of Cuba', 'common_name' => null, 'flag_emoji' => '🇨🇺'],
|
||||
['alpha2' => 'CV', 'alpha3' => 'CPV', 'numeric' => '132', 'name' => 'Cabo Verde', 'official_name' => 'Republic of Cabo Verde', 'common_name' => null, 'flag_emoji' => '🇨🇻'],
|
||||
['alpha2' => 'CW', 'alpha3' => 'CUW', 'numeric' => '531', 'name' => 'Curaçao', 'official_name' => 'Curaçao', 'common_name' => null, 'flag_emoji' => '🇨🇼'],
|
||||
['alpha2' => 'CX', 'alpha3' => 'CXR', 'numeric' => '162', 'name' => 'Christmas Island', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇨🇽'],
|
||||
['alpha2' => 'CY', 'alpha3' => 'CYP', 'numeric' => '196', 'name' => 'Cyprus', 'official_name' => 'Republic of Cyprus', 'common_name' => null, 'flag_emoji' => '🇨🇾'],
|
||||
['alpha2' => 'CZ', 'alpha3' => 'CZE', 'numeric' => '203', 'name' => 'Czechia', 'official_name' => 'Czech Republic', 'common_name' => null, 'flag_emoji' => '🇨🇿'],
|
||||
['alpha2' => 'DE', 'alpha3' => 'DEU', 'numeric' => '276', 'name' => 'Germany', 'official_name' => 'Federal Republic of Germany', 'common_name' => null, 'flag_emoji' => '🇩🇪'],
|
||||
['alpha2' => 'DJ', 'alpha3' => 'DJI', 'numeric' => '262', 'name' => 'Djibouti', 'official_name' => 'Republic of Djibouti', 'common_name' => null, 'flag_emoji' => '🇩🇯'],
|
||||
['alpha2' => 'DK', 'alpha3' => 'DNK', 'numeric' => '208', 'name' => 'Denmark', 'official_name' => 'Kingdom of Denmark', 'common_name' => null, 'flag_emoji' => '🇩🇰'],
|
||||
['alpha2' => 'DM', 'alpha3' => 'DMA', 'numeric' => '212', 'name' => 'Dominica', 'official_name' => 'Commonwealth of Dominica', 'common_name' => null, 'flag_emoji' => '🇩🇲'],
|
||||
['alpha2' => 'DO', 'alpha3' => 'DOM', 'numeric' => '214', 'name' => 'Dominican Republic', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇩🇴'],
|
||||
['alpha2' => 'DZ', 'alpha3' => 'DZA', 'numeric' => '012', 'name' => 'Algeria', 'official_name' => 'People\'s Democratic Republic of Algeria', 'common_name' => null, 'flag_emoji' => '🇩🇿'],
|
||||
['alpha2' => 'EC', 'alpha3' => 'ECU', 'numeric' => '218', 'name' => 'Ecuador', 'official_name' => 'Republic of Ecuador', 'common_name' => null, 'flag_emoji' => '🇪🇨'],
|
||||
['alpha2' => 'EE', 'alpha3' => 'EST', 'numeric' => '233', 'name' => 'Estonia', 'official_name' => 'Republic of Estonia', 'common_name' => null, 'flag_emoji' => '🇪🇪'],
|
||||
['alpha2' => 'EG', 'alpha3' => 'EGY', 'numeric' => '818', 'name' => 'Egypt', 'official_name' => 'Arab Republic of Egypt', 'common_name' => null, 'flag_emoji' => '🇪🇬'],
|
||||
['alpha2' => 'EH', 'alpha3' => 'ESH', 'numeric' => '732', 'name' => 'Western Sahara', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇪🇭'],
|
||||
['alpha2' => 'ER', 'alpha3' => 'ERI', 'numeric' => '232', 'name' => 'Eritrea', 'official_name' => 'the State of Eritrea', 'common_name' => null, 'flag_emoji' => '🇪🇷'],
|
||||
['alpha2' => 'ES', 'alpha3' => 'ESP', 'numeric' => '724', 'name' => 'Spain', 'official_name' => 'Kingdom of Spain', 'common_name' => null, 'flag_emoji' => '🇪🇸'],
|
||||
['alpha2' => 'ET', 'alpha3' => 'ETH', 'numeric' => '231', 'name' => 'Ethiopia', 'official_name' => 'Federal Democratic Republic of Ethiopia', 'common_name' => null, 'flag_emoji' => '🇪🇹'],
|
||||
['alpha2' => 'FI', 'alpha3' => 'FIN', 'numeric' => '246', 'name' => 'Finland', 'official_name' => 'Republic of Finland', 'common_name' => null, 'flag_emoji' => '🇫🇮'],
|
||||
['alpha2' => 'FJ', 'alpha3' => 'FJI', 'numeric' => '242', 'name' => 'Fiji', 'official_name' => 'Republic of Fiji', 'common_name' => null, 'flag_emoji' => '🇫🇯'],
|
||||
['alpha2' => 'FK', 'alpha3' => 'FLK', 'numeric' => '238', 'name' => 'Falkland Islands (Malvinas)', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇫🇰'],
|
||||
['alpha2' => 'FM', 'alpha3' => 'FSM', 'numeric' => '583', 'name' => 'Micronesia, Federated States of', 'official_name' => 'Federated States of Micronesia', 'common_name' => null, 'flag_emoji' => '🇫🇲'],
|
||||
['alpha2' => 'FO', 'alpha3' => 'FRO', 'numeric' => '234', 'name' => 'Faroe Islands', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇫🇴'],
|
||||
['alpha2' => 'FR', 'alpha3' => 'FRA', 'numeric' => '250', 'name' => 'France', 'official_name' => 'French Republic', 'common_name' => null, 'flag_emoji' => '🇫🇷'],
|
||||
['alpha2' => 'GA', 'alpha3' => 'GAB', 'numeric' => '266', 'name' => 'Gabon', 'official_name' => 'Gabonese Republic', 'common_name' => null, 'flag_emoji' => '🇬🇦'],
|
||||
['alpha2' => 'GB', 'alpha3' => 'GBR', 'numeric' => '826', 'name' => 'United Kingdom', 'official_name' => 'United Kingdom of Great Britain and Northern Ireland', 'common_name' => null, 'flag_emoji' => '🇬🇧'],
|
||||
['alpha2' => 'GD', 'alpha3' => 'GRD', 'numeric' => '308', 'name' => 'Grenada', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇬🇩'],
|
||||
['alpha2' => 'GE', 'alpha3' => 'GEO', 'numeric' => '268', 'name' => 'Georgia', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇬🇪'],
|
||||
['alpha2' => 'GF', 'alpha3' => 'GUF', 'numeric' => '254', 'name' => 'French Guiana', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇬🇫'],
|
||||
['alpha2' => 'GG', 'alpha3' => 'GGY', 'numeric' => '831', 'name' => 'Guernsey', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇬🇬'],
|
||||
['alpha2' => 'GH', 'alpha3' => 'GHA', 'numeric' => '288', 'name' => 'Ghana', 'official_name' => 'Republic of Ghana', 'common_name' => null, 'flag_emoji' => '🇬🇭'],
|
||||
['alpha2' => 'GI', 'alpha3' => 'GIB', 'numeric' => '292', 'name' => 'Gibraltar', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇬🇮'],
|
||||
['alpha2' => 'GL', 'alpha3' => 'GRL', 'numeric' => '304', 'name' => 'Greenland', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇬🇱'],
|
||||
['alpha2' => 'GM', 'alpha3' => 'GMB', 'numeric' => '270', 'name' => 'Gambia', 'official_name' => 'Republic of the Gambia', 'common_name' => null, 'flag_emoji' => '🇬🇲'],
|
||||
['alpha2' => 'GN', 'alpha3' => 'GIN', 'numeric' => '324', 'name' => 'Guinea', 'official_name' => 'Republic of Guinea', 'common_name' => null, 'flag_emoji' => '🇬🇳'],
|
||||
['alpha2' => 'GP', 'alpha3' => 'GLP', 'numeric' => '312', 'name' => 'Guadeloupe', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇬🇵'],
|
||||
['alpha2' => 'GQ', 'alpha3' => 'GNQ', 'numeric' => '226', 'name' => 'Equatorial Guinea', 'official_name' => 'Republic of Equatorial Guinea', 'common_name' => null, 'flag_emoji' => '🇬🇶'],
|
||||
['alpha2' => 'GR', 'alpha3' => 'GRC', 'numeric' => '300', 'name' => 'Greece', 'official_name' => 'Hellenic Republic', 'common_name' => null, 'flag_emoji' => '🇬🇷'],
|
||||
['alpha2' => 'GS', 'alpha3' => 'SGS', 'numeric' => '239', 'name' => 'South Georgia and the South Sandwich Islands', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇬🇸'],
|
||||
['alpha2' => 'GT', 'alpha3' => 'GTM', 'numeric' => '320', 'name' => 'Guatemala', 'official_name' => 'Republic of Guatemala', 'common_name' => null, 'flag_emoji' => '🇬🇹'],
|
||||
['alpha2' => 'GU', 'alpha3' => 'GUM', 'numeric' => '316', 'name' => 'Guam', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇬🇺'],
|
||||
['alpha2' => 'GW', 'alpha3' => 'GNB', 'numeric' => '624', 'name' => 'Guinea-Bissau', 'official_name' => 'Republic of Guinea-Bissau', 'common_name' => null, 'flag_emoji' => '🇬🇼'],
|
||||
['alpha2' => 'GY', 'alpha3' => 'GUY', 'numeric' => '328', 'name' => 'Guyana', 'official_name' => 'Republic of Guyana', 'common_name' => null, 'flag_emoji' => '🇬🇾'],
|
||||
['alpha2' => 'HK', 'alpha3' => 'HKG', 'numeric' => '344', 'name' => 'Hong Kong', 'official_name' => 'Hong Kong Special Administrative Region of China', 'common_name' => null, 'flag_emoji' => '🇭🇰'],
|
||||
['alpha2' => 'HM', 'alpha3' => 'HMD', 'numeric' => '334', 'name' => 'Heard Island and McDonald Islands', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇭🇲'],
|
||||
['alpha2' => 'HN', 'alpha3' => 'HND', 'numeric' => '340', 'name' => 'Honduras', 'official_name' => 'Republic of Honduras', 'common_name' => null, 'flag_emoji' => '🇭🇳'],
|
||||
['alpha2' => 'HR', 'alpha3' => 'HRV', 'numeric' => '191', 'name' => 'Croatia', 'official_name' => 'Republic of Croatia', 'common_name' => null, 'flag_emoji' => '🇭🇷'],
|
||||
['alpha2' => 'HT', 'alpha3' => 'HTI', 'numeric' => '332', 'name' => 'Haiti', 'official_name' => 'Republic of Haiti', 'common_name' => null, 'flag_emoji' => '🇭🇹'],
|
||||
['alpha2' => 'HU', 'alpha3' => 'HUN', 'numeric' => '348', 'name' => 'Hungary', 'official_name' => 'Hungary', 'common_name' => null, 'flag_emoji' => '🇭🇺'],
|
||||
['alpha2' => 'ID', 'alpha3' => 'IDN', 'numeric' => '360', 'name' => 'Indonesia', 'official_name' => 'Republic of Indonesia', 'common_name' => null, 'flag_emoji' => '🇮🇩'],
|
||||
['alpha2' => 'IE', 'alpha3' => 'IRL', 'numeric' => '372', 'name' => 'Ireland', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇮🇪'],
|
||||
['alpha2' => 'IL', 'alpha3' => 'ISR', 'numeric' => '376', 'name' => 'Israel', 'official_name' => 'State of Israel', 'common_name' => null, 'flag_emoji' => '🇮🇱'],
|
||||
['alpha2' => 'IM', 'alpha3' => 'IMN', 'numeric' => '833', 'name' => 'Isle of Man', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇮🇲'],
|
||||
['alpha2' => 'IN', 'alpha3' => 'IND', 'numeric' => '356', 'name' => 'India', 'official_name' => 'Republic of India', 'common_name' => null, 'flag_emoji' => '🇮🇳'],
|
||||
['alpha2' => 'IO', 'alpha3' => 'IOT', 'numeric' => '086', 'name' => 'British Indian Ocean Territory', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇮🇴'],
|
||||
['alpha2' => 'IQ', 'alpha3' => 'IRQ', 'numeric' => '368', 'name' => 'Iraq', 'official_name' => 'Republic of Iraq', 'common_name' => null, 'flag_emoji' => '🇮🇶'],
|
||||
['alpha2' => 'IR', 'alpha3' => 'IRN', 'numeric' => '364', 'name' => 'Iran, Islamic Republic of', 'official_name' => 'Islamic Republic of Iran', 'common_name' => 'Iran', 'flag_emoji' => '🇮🇷'],
|
||||
['alpha2' => 'IS', 'alpha3' => 'ISL', 'numeric' => '352', 'name' => 'Iceland', 'official_name' => 'Republic of Iceland', 'common_name' => null, 'flag_emoji' => '🇮🇸'],
|
||||
['alpha2' => 'IT', 'alpha3' => 'ITA', 'numeric' => '380', 'name' => 'Italy', 'official_name' => 'Italian Republic', 'common_name' => null, 'flag_emoji' => '🇮🇹'],
|
||||
['alpha2' => 'JE', 'alpha3' => 'JEY', 'numeric' => '832', 'name' => 'Jersey', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇯🇪'],
|
||||
['alpha2' => 'JM', 'alpha3' => 'JAM', 'numeric' => '388', 'name' => 'Jamaica', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇯🇲'],
|
||||
['alpha2' => 'JO', 'alpha3' => 'JOR', 'numeric' => '400', 'name' => 'Jordan', 'official_name' => 'Hashemite Kingdom of Jordan', 'common_name' => null, 'flag_emoji' => '🇯🇴'],
|
||||
['alpha2' => 'JP', 'alpha3' => 'JPN', 'numeric' => '392', 'name' => 'Japan', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇯🇵'],
|
||||
['alpha2' => 'KE', 'alpha3' => 'KEN', 'numeric' => '404', 'name' => 'Kenya', 'official_name' => 'Republic of Kenya', 'common_name' => null, 'flag_emoji' => '🇰🇪'],
|
||||
['alpha2' => 'KG', 'alpha3' => 'KGZ', 'numeric' => '417', 'name' => 'Kyrgyzstan', 'official_name' => 'Kyrgyz Republic', 'common_name' => null, 'flag_emoji' => '🇰🇬'],
|
||||
['alpha2' => 'KH', 'alpha3' => 'KHM', 'numeric' => '116', 'name' => 'Cambodia', 'official_name' => 'Kingdom of Cambodia', 'common_name' => null, 'flag_emoji' => '🇰🇭'],
|
||||
['alpha2' => 'KI', 'alpha3' => 'KIR', 'numeric' => '296', 'name' => 'Kiribati', 'official_name' => 'Republic of Kiribati', 'common_name' => null, 'flag_emoji' => '🇰🇮'],
|
||||
['alpha2' => 'KM', 'alpha3' => 'COM', 'numeric' => '174', 'name' => 'Comoros', 'official_name' => 'Union of the Comoros', 'common_name' => null, 'flag_emoji' => '🇰🇲'],
|
||||
['alpha2' => 'KN', 'alpha3' => 'KNA', 'numeric' => '659', 'name' => 'Saint Kitts and Nevis', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇰🇳'],
|
||||
['alpha2' => 'KP', 'alpha3' => 'PRK', 'numeric' => '408', 'name' => 'Korea, Democratic People\'s Republic of', 'official_name' => 'Democratic People\'s Republic of Korea', 'common_name' => 'North Korea', 'flag_emoji' => '🇰🇵'],
|
||||
['alpha2' => 'KR', 'alpha3' => 'KOR', 'numeric' => '410', 'name' => 'Korea, Republic of', 'official_name' => null, 'common_name' => 'South Korea', 'flag_emoji' => '🇰🇷'],
|
||||
['alpha2' => 'KW', 'alpha3' => 'KWT', 'numeric' => '414', 'name' => 'Kuwait', 'official_name' => 'State of Kuwait', 'common_name' => null, 'flag_emoji' => '🇰🇼'],
|
||||
['alpha2' => 'KY', 'alpha3' => 'CYM', 'numeric' => '136', 'name' => 'Cayman Islands', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇰🇾'],
|
||||
['alpha2' => 'KZ', 'alpha3' => 'KAZ', 'numeric' => '398', 'name' => 'Kazakhstan', 'official_name' => 'Republic of Kazakhstan', 'common_name' => null, 'flag_emoji' => '🇰🇿'],
|
||||
['alpha2' => 'LA', 'alpha3' => 'LAO', 'numeric' => '418', 'name' => 'Lao People\'s Democratic Republic', 'official_name' => null, 'common_name' => 'Laos', 'flag_emoji' => '🇱🇦'],
|
||||
['alpha2' => 'LB', 'alpha3' => 'LBN', 'numeric' => '422', 'name' => 'Lebanon', 'official_name' => 'Lebanese Republic', 'common_name' => null, 'flag_emoji' => '🇱🇧'],
|
||||
['alpha2' => 'LC', 'alpha3' => 'LCA', 'numeric' => '662', 'name' => 'Saint Lucia', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇱🇨'],
|
||||
['alpha2' => 'LI', 'alpha3' => 'LIE', 'numeric' => '438', 'name' => 'Liechtenstein', 'official_name' => 'Principality of Liechtenstein', 'common_name' => null, 'flag_emoji' => '🇱🇮'],
|
||||
['alpha2' => 'LK', 'alpha3' => 'LKA', 'numeric' => '144', 'name' => 'Sri Lanka', 'official_name' => 'Democratic Socialist Republic of Sri Lanka', 'common_name' => null, 'flag_emoji' => '🇱🇰'],
|
||||
['alpha2' => 'LR', 'alpha3' => 'LBR', 'numeric' => '430', 'name' => 'Liberia', 'official_name' => 'Republic of Liberia', 'common_name' => null, 'flag_emoji' => '🇱🇷'],
|
||||
['alpha2' => 'LS', 'alpha3' => 'LSO', 'numeric' => '426', 'name' => 'Lesotho', 'official_name' => 'Kingdom of Lesotho', 'common_name' => null, 'flag_emoji' => '🇱🇸'],
|
||||
['alpha2' => 'LT', 'alpha3' => 'LTU', 'numeric' => '440', 'name' => 'Lithuania', 'official_name' => 'Republic of Lithuania', 'common_name' => null, 'flag_emoji' => '🇱🇹'],
|
||||
['alpha2' => 'LU', 'alpha3' => 'LUX', 'numeric' => '442', 'name' => 'Luxembourg', 'official_name' => 'Grand Duchy of Luxembourg', 'common_name' => null, 'flag_emoji' => '🇱🇺'],
|
||||
['alpha2' => 'LV', 'alpha3' => 'LVA', 'numeric' => '428', 'name' => 'Latvia', 'official_name' => 'Republic of Latvia', 'common_name' => null, 'flag_emoji' => '🇱🇻'],
|
||||
['alpha2' => 'LY', 'alpha3' => 'LBY', 'numeric' => '434', 'name' => 'Libya', 'official_name' => 'Libya', 'common_name' => null, 'flag_emoji' => '🇱🇾'],
|
||||
['alpha2' => 'MA', 'alpha3' => 'MAR', 'numeric' => '504', 'name' => 'Morocco', 'official_name' => 'Kingdom of Morocco', 'common_name' => null, 'flag_emoji' => '🇲🇦'],
|
||||
['alpha2' => 'MC', 'alpha3' => 'MCO', 'numeric' => '492', 'name' => 'Monaco', 'official_name' => 'Principality of Monaco', 'common_name' => null, 'flag_emoji' => '🇲🇨'],
|
||||
['alpha2' => 'MD', 'alpha3' => 'MDA', 'numeric' => '498', 'name' => 'Moldova, Republic of', 'official_name' => 'Republic of Moldova', 'common_name' => 'Moldova', 'flag_emoji' => '🇲🇩'],
|
||||
['alpha2' => 'ME', 'alpha3' => 'MNE', 'numeric' => '499', 'name' => 'Montenegro', 'official_name' => 'Montenegro', 'common_name' => null, 'flag_emoji' => '🇲🇪'],
|
||||
['alpha2' => 'MF', 'alpha3' => 'MAF', 'numeric' => '663', 'name' => 'Saint Martin (French part)', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇲🇫'],
|
||||
['alpha2' => 'MG', 'alpha3' => 'MDG', 'numeric' => '450', 'name' => 'Madagascar', 'official_name' => 'Republic of Madagascar', 'common_name' => null, 'flag_emoji' => '🇲🇬'],
|
||||
['alpha2' => 'MH', 'alpha3' => 'MHL', 'numeric' => '584', 'name' => 'Marshall Islands', 'official_name' => 'Republic of the Marshall Islands', 'common_name' => null, 'flag_emoji' => '🇲🇭'],
|
||||
['alpha2' => 'MK', 'alpha3' => 'MKD', 'numeric' => '807', 'name' => 'North Macedonia', 'official_name' => 'Republic of North Macedonia', 'common_name' => null, 'flag_emoji' => '🇲🇰'],
|
||||
['alpha2' => 'ML', 'alpha3' => 'MLI', 'numeric' => '466', 'name' => 'Mali', 'official_name' => 'Republic of Mali', 'common_name' => null, 'flag_emoji' => '🇲🇱'],
|
||||
['alpha2' => 'MM', 'alpha3' => 'MMR', 'numeric' => '104', 'name' => 'Myanmar', 'official_name' => 'Republic of Myanmar', 'common_name' => null, 'flag_emoji' => '🇲🇲'],
|
||||
['alpha2' => 'MN', 'alpha3' => 'MNG', 'numeric' => '496', 'name' => 'Mongolia', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇲🇳'],
|
||||
['alpha2' => 'MO', 'alpha3' => 'MAC', 'numeric' => '446', 'name' => 'Macao', 'official_name' => 'Macao Special Administrative Region of China', 'common_name' => null, 'flag_emoji' => '🇲🇴'],
|
||||
['alpha2' => 'MP', 'alpha3' => 'MNP', 'numeric' => '580', 'name' => 'Northern Mariana Islands', 'official_name' => 'Commonwealth of the Northern Mariana Islands', 'common_name' => null, 'flag_emoji' => '🇲🇵'],
|
||||
['alpha2' => 'MQ', 'alpha3' => 'MTQ', 'numeric' => '474', 'name' => 'Martinique', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇲🇶'],
|
||||
['alpha2' => 'MR', 'alpha3' => 'MRT', 'numeric' => '478', 'name' => 'Mauritania', 'official_name' => 'Islamic Republic of Mauritania', 'common_name' => null, 'flag_emoji' => '🇲🇷'],
|
||||
['alpha2' => 'MS', 'alpha3' => 'MSR', 'numeric' => '500', 'name' => 'Montserrat', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇲🇸'],
|
||||
['alpha2' => 'MT', 'alpha3' => 'MLT', 'numeric' => '470', 'name' => 'Malta', 'official_name' => 'Republic of Malta', 'common_name' => null, 'flag_emoji' => '🇲🇹'],
|
||||
['alpha2' => 'MU', 'alpha3' => 'MUS', 'numeric' => '480', 'name' => 'Mauritius', 'official_name' => 'Republic of Mauritius', 'common_name' => null, 'flag_emoji' => '🇲🇺'],
|
||||
['alpha2' => 'MV', 'alpha3' => 'MDV', 'numeric' => '462', 'name' => 'Maldives', 'official_name' => 'Republic of Maldives', 'common_name' => null, 'flag_emoji' => '🇲🇻'],
|
||||
['alpha2' => 'MW', 'alpha3' => 'MWI', 'numeric' => '454', 'name' => 'Malawi', 'official_name' => 'Republic of Malawi', 'common_name' => null, 'flag_emoji' => '🇲🇼'],
|
||||
['alpha2' => 'MX', 'alpha3' => 'MEX', 'numeric' => '484', 'name' => 'Mexico', 'official_name' => 'United Mexican States', 'common_name' => null, 'flag_emoji' => '🇲🇽'],
|
||||
['alpha2' => 'MY', 'alpha3' => 'MYS', 'numeric' => '458', 'name' => 'Malaysia', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇲🇾'],
|
||||
['alpha2' => 'MZ', 'alpha3' => 'MOZ', 'numeric' => '508', 'name' => 'Mozambique', 'official_name' => 'Republic of Mozambique', 'common_name' => null, 'flag_emoji' => '🇲🇿'],
|
||||
['alpha2' => 'NA', 'alpha3' => 'NAM', 'numeric' => '516', 'name' => 'Namibia', 'official_name' => 'Republic of Namibia', 'common_name' => null, 'flag_emoji' => '🇳🇦'],
|
||||
['alpha2' => 'NC', 'alpha3' => 'NCL', 'numeric' => '540', 'name' => 'New Caledonia', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇳🇨'],
|
||||
['alpha2' => 'NE', 'alpha3' => 'NER', 'numeric' => '562', 'name' => 'Niger', 'official_name' => 'Republic of the Niger', 'common_name' => null, 'flag_emoji' => '🇳🇪'],
|
||||
['alpha2' => 'NF', 'alpha3' => 'NFK', 'numeric' => '574', 'name' => 'Norfolk Island', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇳🇫'],
|
||||
['alpha2' => 'NG', 'alpha3' => 'NGA', 'numeric' => '566', 'name' => 'Nigeria', 'official_name' => 'Federal Republic of Nigeria', 'common_name' => null, 'flag_emoji' => '🇳🇬'],
|
||||
['alpha2' => 'NI', 'alpha3' => 'NIC', 'numeric' => '558', 'name' => 'Nicaragua', 'official_name' => 'Republic of Nicaragua', 'common_name' => null, 'flag_emoji' => '🇳🇮'],
|
||||
['alpha2' => 'NL', 'alpha3' => 'NLD', 'numeric' => '528', 'name' => 'Netherlands', 'official_name' => 'Kingdom of the Netherlands', 'common_name' => null, 'flag_emoji' => '🇳🇱'],
|
||||
['alpha2' => 'NO', 'alpha3' => 'NOR', 'numeric' => '578', 'name' => 'Norway', 'official_name' => 'Kingdom of Norway', 'common_name' => null, 'flag_emoji' => '🇳🇴'],
|
||||
['alpha2' => 'NP', 'alpha3' => 'NPL', 'numeric' => '524', 'name' => 'Nepal', 'official_name' => 'Federal Democratic Republic of Nepal', 'common_name' => null, 'flag_emoji' => '🇳🇵'],
|
||||
['alpha2' => 'NR', 'alpha3' => 'NRU', 'numeric' => '520', 'name' => 'Nauru', 'official_name' => 'Republic of Nauru', 'common_name' => null, 'flag_emoji' => '🇳🇷'],
|
||||
['alpha2' => 'NU', 'alpha3' => 'NIU', 'numeric' => '570', 'name' => 'Niue', 'official_name' => 'Niue', 'common_name' => null, 'flag_emoji' => '🇳🇺'],
|
||||
['alpha2' => 'NZ', 'alpha3' => 'NZL', 'numeric' => '554', 'name' => 'New Zealand', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇳🇿'],
|
||||
['alpha2' => 'OM', 'alpha3' => 'OMN', 'numeric' => '512', 'name' => 'Oman', 'official_name' => 'Sultanate of Oman', 'common_name' => null, 'flag_emoji' => '🇴🇲'],
|
||||
['alpha2' => 'PA', 'alpha3' => 'PAN', 'numeric' => '591', 'name' => 'Panama', 'official_name' => 'Republic of Panama', 'common_name' => null, 'flag_emoji' => '🇵🇦'],
|
||||
['alpha2' => 'PE', 'alpha3' => 'PER', 'numeric' => '604', 'name' => 'Peru', 'official_name' => 'Republic of Peru', 'common_name' => null, 'flag_emoji' => '🇵🇪'],
|
||||
['alpha2' => 'PF', 'alpha3' => 'PYF', 'numeric' => '258', 'name' => 'French Polynesia', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇵🇫'],
|
||||
['alpha2' => 'PG', 'alpha3' => 'PNG', 'numeric' => '598', 'name' => 'Papua New Guinea', 'official_name' => 'Independent State of Papua New Guinea', 'common_name' => null, 'flag_emoji' => '🇵🇬'],
|
||||
['alpha2' => 'PH', 'alpha3' => 'PHL', 'numeric' => '608', 'name' => 'Philippines', 'official_name' => 'Republic of the Philippines', 'common_name' => null, 'flag_emoji' => '🇵🇭'],
|
||||
['alpha2' => 'PK', 'alpha3' => 'PAK', 'numeric' => '586', 'name' => 'Pakistan', 'official_name' => 'Islamic Republic of Pakistan', 'common_name' => null, 'flag_emoji' => '🇵🇰'],
|
||||
['alpha2' => 'PL', 'alpha3' => 'POL', 'numeric' => '616', 'name' => 'Poland', 'official_name' => 'Republic of Poland', 'common_name' => null, 'flag_emoji' => '🇵🇱'],
|
||||
['alpha2' => 'PM', 'alpha3' => 'SPM', 'numeric' => '666', 'name' => 'Saint Pierre and Miquelon', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇵🇲'],
|
||||
['alpha2' => 'PN', 'alpha3' => 'PCN', 'numeric' => '612', 'name' => 'Pitcairn', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇵🇳'],
|
||||
['alpha2' => 'PR', 'alpha3' => 'PRI', 'numeric' => '630', 'name' => 'Puerto Rico', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇵🇷'],
|
||||
['alpha2' => 'PS', 'alpha3' => 'PSE', 'numeric' => '275', 'name' => 'Palestine, State of', 'official_name' => 'the State of Palestine', 'common_name' => null, 'flag_emoji' => '🇵🇸'],
|
||||
['alpha2' => 'PT', 'alpha3' => 'PRT', 'numeric' => '620', 'name' => 'Portugal', 'official_name' => 'Portuguese Republic', 'common_name' => null, 'flag_emoji' => '🇵🇹'],
|
||||
['alpha2' => 'PW', 'alpha3' => 'PLW', 'numeric' => '585', 'name' => 'Palau', 'official_name' => 'Republic of Palau', 'common_name' => null, 'flag_emoji' => '🇵🇼'],
|
||||
['alpha2' => 'PY', 'alpha3' => 'PRY', 'numeric' => '600', 'name' => 'Paraguay', 'official_name' => 'Republic of Paraguay', 'common_name' => null, 'flag_emoji' => '🇵🇾'],
|
||||
['alpha2' => 'QA', 'alpha3' => 'QAT', 'numeric' => '634', 'name' => 'Qatar', 'official_name' => 'State of Qatar', 'common_name' => null, 'flag_emoji' => '🇶🇦'],
|
||||
['alpha2' => 'RE', 'alpha3' => 'REU', 'numeric' => '638', 'name' => 'Réunion', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇷🇪'],
|
||||
['alpha2' => 'RO', 'alpha3' => 'ROU', 'numeric' => '642', 'name' => 'Romania', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇷🇴'],
|
||||
['alpha2' => 'RS', 'alpha3' => 'SRB', 'numeric' => '688', 'name' => 'Serbia', 'official_name' => 'Republic of Serbia', 'common_name' => null, 'flag_emoji' => '🇷🇸'],
|
||||
['alpha2' => 'RU', 'alpha3' => 'RUS', 'numeric' => '643', 'name' => 'Russian Federation', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇷🇺'],
|
||||
['alpha2' => 'RW', 'alpha3' => 'RWA', 'numeric' => '646', 'name' => 'Rwanda', 'official_name' => 'Rwandese Republic', 'common_name' => null, 'flag_emoji' => '🇷🇼'],
|
||||
['alpha2' => 'SA', 'alpha3' => 'SAU', 'numeric' => '682', 'name' => 'Saudi Arabia', 'official_name' => 'Kingdom of Saudi Arabia', 'common_name' => null, 'flag_emoji' => '🇸🇦'],
|
||||
['alpha2' => 'SB', 'alpha3' => 'SLB', 'numeric' => '090', 'name' => 'Solomon Islands', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇸🇧'],
|
||||
['alpha2' => 'SC', 'alpha3' => 'SYC', 'numeric' => '690', 'name' => 'Seychelles', 'official_name' => 'Republic of Seychelles', 'common_name' => null, 'flag_emoji' => '🇸🇨'],
|
||||
['alpha2' => 'SD', 'alpha3' => 'SDN', 'numeric' => '729', 'name' => 'Sudan', 'official_name' => 'Republic of the Sudan', 'common_name' => null, 'flag_emoji' => '🇸🇩'],
|
||||
['alpha2' => 'SE', 'alpha3' => 'SWE', 'numeric' => '752', 'name' => 'Sweden', 'official_name' => 'Kingdom of Sweden', 'common_name' => null, 'flag_emoji' => '🇸🇪'],
|
||||
['alpha2' => 'SG', 'alpha3' => 'SGP', 'numeric' => '702', 'name' => 'Singapore', 'official_name' => 'Republic of Singapore', 'common_name' => null, 'flag_emoji' => '🇸🇬'],
|
||||
['alpha2' => 'SH', 'alpha3' => 'SHN', 'numeric' => '654', 'name' => 'Saint Helena, Ascension and Tristan da Cunha', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇸🇭'],
|
||||
['alpha2' => 'SI', 'alpha3' => 'SVN', 'numeric' => '705', 'name' => 'Slovenia', 'official_name' => 'Republic of Slovenia', 'common_name' => null, 'flag_emoji' => '🇸🇮'],
|
||||
['alpha2' => 'SJ', 'alpha3' => 'SJM', 'numeric' => '744', 'name' => 'Svalbard and Jan Mayen', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇸🇯'],
|
||||
['alpha2' => 'SK', 'alpha3' => 'SVK', 'numeric' => '703', 'name' => 'Slovakia', 'official_name' => 'Slovak Republic', 'common_name' => null, 'flag_emoji' => '🇸🇰'],
|
||||
['alpha2' => 'SL', 'alpha3' => 'SLE', 'numeric' => '694', 'name' => 'Sierra Leone', 'official_name' => 'Republic of Sierra Leone', 'common_name' => null, 'flag_emoji' => '🇸🇱'],
|
||||
['alpha2' => 'SM', 'alpha3' => 'SMR', 'numeric' => '674', 'name' => 'San Marino', 'official_name' => 'Republic of San Marino', 'common_name' => null, 'flag_emoji' => '🇸🇲'],
|
||||
['alpha2' => 'SN', 'alpha3' => 'SEN', 'numeric' => '686', 'name' => 'Senegal', 'official_name' => 'Republic of Senegal', 'common_name' => null, 'flag_emoji' => '🇸🇳'],
|
||||
['alpha2' => 'SO', 'alpha3' => 'SOM', 'numeric' => '706', 'name' => 'Somalia', 'official_name' => 'Federal Republic of Somalia', 'common_name' => null, 'flag_emoji' => '🇸🇴'],
|
||||
['alpha2' => 'SR', 'alpha3' => 'SUR', 'numeric' => '740', 'name' => 'Suriname', 'official_name' => 'Republic of Suriname', 'common_name' => null, 'flag_emoji' => '🇸🇷'],
|
||||
['alpha2' => 'SS', 'alpha3' => 'SSD', 'numeric' => '728', 'name' => 'South Sudan', 'official_name' => 'Republic of South Sudan', 'common_name' => null, 'flag_emoji' => '🇸🇸'],
|
||||
['alpha2' => 'ST', 'alpha3' => 'STP', 'numeric' => '678', 'name' => 'Sao Tome and Principe', 'official_name' => 'Democratic Republic of Sao Tome and Principe', 'common_name' => null, 'flag_emoji' => '🇸🇹'],
|
||||
['alpha2' => 'SV', 'alpha3' => 'SLV', 'numeric' => '222', 'name' => 'El Salvador', 'official_name' => 'Republic of El Salvador', 'common_name' => null, 'flag_emoji' => '🇸🇻'],
|
||||
['alpha2' => 'SX', 'alpha3' => 'SXM', 'numeric' => '534', 'name' => 'Sint Maarten (Dutch part)', 'official_name' => 'Sint Maarten (Dutch part)', 'common_name' => null, 'flag_emoji' => '🇸🇽'],
|
||||
['alpha2' => 'SY', 'alpha3' => 'SYR', 'numeric' => '760', 'name' => 'Syrian Arab Republic', 'official_name' => null, 'common_name' => 'Syria', 'flag_emoji' => '🇸🇾'],
|
||||
['alpha2' => 'SZ', 'alpha3' => 'SWZ', 'numeric' => '748', 'name' => 'Eswatini', 'official_name' => 'Kingdom of Eswatini', 'common_name' => null, 'flag_emoji' => '🇸🇿'],
|
||||
['alpha2' => 'TC', 'alpha3' => 'TCA', 'numeric' => '796', 'name' => 'Turks and Caicos Islands', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇹🇨'],
|
||||
['alpha2' => 'TD', 'alpha3' => 'TCD', 'numeric' => '148', 'name' => 'Chad', 'official_name' => 'Republic of Chad', 'common_name' => null, 'flag_emoji' => '🇹🇩'],
|
||||
['alpha2' => 'TF', 'alpha3' => 'ATF', 'numeric' => '260', 'name' => 'French Southern Territories', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇹🇫'],
|
||||
['alpha2' => 'TG', 'alpha3' => 'TGO', 'numeric' => '768', 'name' => 'Togo', 'official_name' => 'Togolese Republic', 'common_name' => null, 'flag_emoji' => '🇹🇬'],
|
||||
['alpha2' => 'TH', 'alpha3' => 'THA', 'numeric' => '764', 'name' => 'Thailand', 'official_name' => 'Kingdom of Thailand', 'common_name' => null, 'flag_emoji' => '🇹🇭'],
|
||||
['alpha2' => 'TJ', 'alpha3' => 'TJK', 'numeric' => '762', 'name' => 'Tajikistan', 'official_name' => 'Republic of Tajikistan', 'common_name' => null, 'flag_emoji' => '🇹🇯'],
|
||||
['alpha2' => 'TK', 'alpha3' => 'TKL', 'numeric' => '772', 'name' => 'Tokelau', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇹🇰'],
|
||||
['alpha2' => 'TL', 'alpha3' => 'TLS', 'numeric' => '626', 'name' => 'Timor-Leste', 'official_name' => 'Democratic Republic of Timor-Leste', 'common_name' => null, 'flag_emoji' => '🇹🇱'],
|
||||
['alpha2' => 'TM', 'alpha3' => 'TKM', 'numeric' => '795', 'name' => 'Turkmenistan', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇹🇲'],
|
||||
['alpha2' => 'TN', 'alpha3' => 'TUN', 'numeric' => '788', 'name' => 'Tunisia', 'official_name' => 'Republic of Tunisia', 'common_name' => null, 'flag_emoji' => '🇹🇳'],
|
||||
['alpha2' => 'TO', 'alpha3' => 'TON', 'numeric' => '776', 'name' => 'Tonga', 'official_name' => 'Kingdom of Tonga', 'common_name' => null, 'flag_emoji' => '🇹🇴'],
|
||||
['alpha2' => 'TR', 'alpha3' => 'TUR', 'numeric' => '792', 'name' => 'Türkiye', 'official_name' => 'Republic of Türkiye', 'common_name' => null, 'flag_emoji' => '🇹🇷'],
|
||||
['alpha2' => 'TT', 'alpha3' => 'TTO', 'numeric' => '780', 'name' => 'Trinidad and Tobago', 'official_name' => 'Republic of Trinidad and Tobago', 'common_name' => null, 'flag_emoji' => '🇹🇹'],
|
||||
['alpha2' => 'TV', 'alpha3' => 'TUV', 'numeric' => '798', 'name' => 'Tuvalu', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇹🇻'],
|
||||
['alpha2' => 'TW', 'alpha3' => 'TWN', 'numeric' => '158', 'name' => 'Taiwan, Province of China', 'official_name' => 'Taiwan, Province of China', 'common_name' => 'Taiwan', 'flag_emoji' => '🇹🇼'],
|
||||
['alpha2' => 'TZ', 'alpha3' => 'TZA', 'numeric' => '834', 'name' => 'Tanzania, United Republic of', 'official_name' => 'United Republic of Tanzania', 'common_name' => 'Tanzania', 'flag_emoji' => '🇹🇿'],
|
||||
['alpha2' => 'UA', 'alpha3' => 'UKR', 'numeric' => '804', 'name' => 'Ukraine', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇺🇦'],
|
||||
['alpha2' => 'UG', 'alpha3' => 'UGA', 'numeric' => '800', 'name' => 'Uganda', 'official_name' => 'Republic of Uganda', 'common_name' => null, 'flag_emoji' => '🇺🇬'],
|
||||
['alpha2' => 'UM', 'alpha3' => 'UMI', 'numeric' => '581', 'name' => 'United States Minor Outlying Islands', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇺🇲'],
|
||||
['alpha2' => 'US', 'alpha3' => 'USA', 'numeric' => '840', 'name' => 'United States', 'official_name' => 'United States of America', 'common_name' => null, 'flag_emoji' => '🇺🇸'],
|
||||
['alpha2' => 'UY', 'alpha3' => 'URY', 'numeric' => '858', 'name' => 'Uruguay', 'official_name' => 'Eastern Republic of Uruguay', 'common_name' => null, 'flag_emoji' => '🇺🇾'],
|
||||
['alpha2' => 'UZ', 'alpha3' => 'UZB', 'numeric' => '860', 'name' => 'Uzbekistan', 'official_name' => 'Republic of Uzbekistan', 'common_name' => null, 'flag_emoji' => '🇺🇿'],
|
||||
['alpha2' => 'VA', 'alpha3' => 'VAT', 'numeric' => '336', 'name' => 'Holy See (Vatican City State)', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇻🇦'],
|
||||
['alpha2' => 'VC', 'alpha3' => 'VCT', 'numeric' => '670', 'name' => 'Saint Vincent and the Grenadines', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇻🇨'],
|
||||
['alpha2' => 'VE', 'alpha3' => 'VEN', 'numeric' => '862', 'name' => 'Venezuela, Bolivarian Republic of', 'official_name' => 'Bolivarian Republic of Venezuela', 'common_name' => 'Venezuela', 'flag_emoji' => '🇻🇪'],
|
||||
['alpha2' => 'VG', 'alpha3' => 'VGB', 'numeric' => '092', 'name' => 'Virgin Islands, British', 'official_name' => 'British Virgin Islands', 'common_name' => null, 'flag_emoji' => '🇻🇬'],
|
||||
['alpha2' => 'VI', 'alpha3' => 'VIR', 'numeric' => '850', 'name' => 'Virgin Islands, U.S.', 'official_name' => 'Virgin Islands of the United States', 'common_name' => null, 'flag_emoji' => '🇻🇮'],
|
||||
['alpha2' => 'VN', 'alpha3' => 'VNM', 'numeric' => '704', 'name' => 'Viet Nam', 'official_name' => 'Socialist Republic of Viet Nam', 'common_name' => 'Vietnam', 'flag_emoji' => '🇻🇳'],
|
||||
['alpha2' => 'VU', 'alpha3' => 'VUT', 'numeric' => '548', 'name' => 'Vanuatu', 'official_name' => 'Republic of Vanuatu', 'common_name' => null, 'flag_emoji' => '🇻🇺'],
|
||||
['alpha2' => 'WF', 'alpha3' => 'WLF', 'numeric' => '876', 'name' => 'Wallis and Futuna', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇼🇫'],
|
||||
['alpha2' => 'WS', 'alpha3' => 'WSM', 'numeric' => '882', 'name' => 'Samoa', 'official_name' => 'Independent State of Samoa', 'common_name' => null, 'flag_emoji' => '🇼🇸'],
|
||||
['alpha2' => 'YE', 'alpha3' => 'YEM', 'numeric' => '887', 'name' => 'Yemen', 'official_name' => 'Republic of Yemen', 'common_name' => null, 'flag_emoji' => '🇾🇪'],
|
||||
['alpha2' => 'YT', 'alpha3' => 'MYT', 'numeric' => '175', 'name' => 'Mayotte', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇾🇹'],
|
||||
['alpha2' => 'ZA', 'alpha3' => 'ZAF', 'numeric' => '710', 'name' => 'South Africa', 'official_name' => 'Republic of South Africa', 'common_name' => null, 'flag_emoji' => '🇿🇦'],
|
||||
['alpha2' => 'ZM', 'alpha3' => 'ZMB', 'numeric' => '894', 'name' => 'Zambia', 'official_name' => 'Republic of Zambia', 'common_name' => null, 'flag_emoji' => '🇿🇲'],
|
||||
['alpha2' => 'ZW', 'alpha3' => 'ZWE', 'numeric' => '716', 'name' => 'Zimbabwe', 'official_name' => 'Republic of Zimbabwe', 'common_name' => null, 'flag_emoji' => '🇿🇼'],
|
||||
];
|
||||
/** @var list<array<string, mixed>> $countries */
|
||||
$countries = json_decode(
|
||||
file_get_contents(dirname(__DIR__) . '/Data/iso_countries.json'),
|
||||
true,
|
||||
flags: JSON_THROW_ON_ERROR,
|
||||
);
|
||||
|
||||
foreach ($countries as $index => $country) {
|
||||
Country::query()->updateOrCreate(
|
||||
|
||||
@@ -8,6 +8,12 @@ use Modules\Countries\Support\Iso3166;
|
||||
|
||||
class StoreCountryRequest extends FormRequest
|
||||
{
|
||||
private const ISO3 = 'size:3';
|
||||
|
||||
private const MAX_STRING = 'max:255';
|
||||
|
||||
private const MAX_SHORT = 'max:16';
|
||||
|
||||
/**
|
||||
* Authorize country reference-data administration.
|
||||
*/
|
||||
@@ -38,29 +44,29 @@ class StoreCountryRequest extends FormRequest
|
||||
{
|
||||
return [
|
||||
'alpha2' => ['required', 'string', 'size:2', 'uppercase', 'unique:countries,alpha2'],
|
||||
'alpha3' => ['required', 'string', 'size:3', 'uppercase', 'unique:countries,alpha3'],
|
||||
'numeric' => ['required', 'string', 'size:3', 'unique:countries,numeric'],
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'official_name' => ['nullable', 'string', 'max:255'],
|
||||
'common_name' => ['nullable', 'string', 'max:255'],
|
||||
'display_name' => ['nullable', 'string', 'max:255'],
|
||||
'native_name' => ['nullable', 'string', 'max:255'],
|
||||
'capital' => ['nullable', 'string', 'max:255'],
|
||||
'flag_emoji' => ['nullable', 'string', 'max:16'],
|
||||
'calling_code' => ['nullable', 'string', 'max:16'],
|
||||
'tld' => ['nullable', 'string', 'max:16'],
|
||||
'currency_code' => ['nullable', 'string', 'size:3', 'uppercase'],
|
||||
'currency_name' => ['nullable', 'string', 'max:255'],
|
||||
'currency_symbol' => ['nullable', 'string', 'max:16'],
|
||||
'alpha3' => ['required', 'string', self::ISO3, 'uppercase', 'unique:countries,alpha3'],
|
||||
'numeric' => ['required', 'string', self::ISO3, 'unique:countries,numeric'],
|
||||
'name' => ['required', 'string', self::MAX_STRING],
|
||||
'official_name' => ['nullable', 'string', self::MAX_STRING],
|
||||
'common_name' => ['nullable', 'string', self::MAX_STRING],
|
||||
'display_name' => ['nullable', 'string', self::MAX_STRING],
|
||||
'native_name' => ['nullable', 'string', self::MAX_STRING],
|
||||
'capital' => ['nullable', 'string', self::MAX_STRING],
|
||||
'flag_emoji' => ['nullable', 'string', self::MAX_SHORT],
|
||||
'calling_code' => ['nullable', 'string', self::MAX_SHORT],
|
||||
'tld' => ['nullable', 'string', self::MAX_SHORT],
|
||||
'currency_code' => ['nullable', 'string', self::ISO3, 'uppercase'],
|
||||
'currency_name' => ['nullable', 'string', self::MAX_STRING],
|
||||
'currency_symbol' => ['nullable', 'string', self::MAX_SHORT],
|
||||
'languages' => ['nullable', 'json'],
|
||||
'timezones' => ['nullable', 'json'],
|
||||
'latitude' => ['nullable', 'numeric', 'between:-90,90'],
|
||||
'longitude' => ['nullable', 'numeric', 'between:-180,180'],
|
||||
'flag_svg_url' => ['nullable', 'url', 'max:255'],
|
||||
'flag_png_url' => ['nullable', 'url', 'max:255'],
|
||||
'flag_svg_url' => ['nullable', 'url', self::MAX_STRING],
|
||||
'flag_png_url' => ['nullable', 'url', self::MAX_STRING],
|
||||
'ioc_code' => ['nullable', 'string', 'max:8'],
|
||||
'fifa_code' => ['nullable', 'string', 'max:8'],
|
||||
'postal_code_format' => ['nullable', 'string', 'max:255'],
|
||||
'postal_code_format' => ['nullable', 'string', self::MAX_STRING],
|
||||
'address_format' => ['nullable', 'string', 'max:5000'],
|
||||
'is_active' => ['required', 'boolean'],
|
||||
'iso_status' => ['required', 'string', Rule::in(Iso3166::statuses())],
|
||||
@@ -70,10 +76,10 @@ class StoreCountryRequest extends FormRequest
|
||||
'continent' => ['nullable', 'string', 'max:64'],
|
||||
'region' => ['nullable', 'string', 'max:100'],
|
||||
'subregion' => ['nullable', 'string', 'max:100'],
|
||||
'intermediate_region' => ['nullable', 'string', 'max:255'],
|
||||
'intermediate_region' => ['nullable', 'string', self::MAX_STRING],
|
||||
'sort_order' => ['nullable', 'integer', 'min:0', 'max:999999'],
|
||||
'source' => ['nullable', 'string', 'max:255'],
|
||||
'source_version' => ['nullable', 'string', 'max:255'],
|
||||
'source' => ['nullable', 'string', self::MAX_STRING],
|
||||
'source_version' => ['nullable', 'string', self::MAX_STRING],
|
||||
'last_synced_at' => ['nullable', 'date'],
|
||||
'metadata' => ['nullable', 'json'],
|
||||
];
|
||||
|
||||
@@ -8,6 +8,12 @@ use Modules\Countries\Support\Iso3166;
|
||||
|
||||
class UpdateCountryRequest extends FormRequest
|
||||
{
|
||||
private const ISO3 = 'size:3';
|
||||
|
||||
private const MAX_STRING = 'max:255';
|
||||
|
||||
private const MAX_SHORT = 'max:16';
|
||||
|
||||
/**
|
||||
* Authorize country reference-data administration.
|
||||
*/
|
||||
@@ -40,29 +46,29 @@ class UpdateCountryRequest extends FormRequest
|
||||
|
||||
return [
|
||||
'alpha2' => ['required', 'string', 'size:2', 'uppercase', Rule::unique('countries', 'alpha2')->ignore($countryId)],
|
||||
'alpha3' => ['required', 'string', 'size:3', 'uppercase', Rule::unique('countries', 'alpha3')->ignore($countryId)],
|
||||
'numeric' => ['required', 'string', 'size:3', Rule::unique('countries', 'numeric')->ignore($countryId)],
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'official_name' => ['nullable', 'string', 'max:255'],
|
||||
'common_name' => ['nullable', 'string', 'max:255'],
|
||||
'display_name' => ['nullable', 'string', 'max:255'],
|
||||
'native_name' => ['nullable', 'string', 'max:255'],
|
||||
'capital' => ['nullable', 'string', 'max:255'],
|
||||
'flag_emoji' => ['nullable', 'string', 'max:16'],
|
||||
'calling_code' => ['nullable', 'string', 'max:16'],
|
||||
'tld' => ['nullable', 'string', 'max:16'],
|
||||
'currency_code' => ['nullable', 'string', 'size:3', 'uppercase'],
|
||||
'currency_name' => ['nullable', 'string', 'max:255'],
|
||||
'currency_symbol' => ['nullable', 'string', 'max:16'],
|
||||
'alpha3' => ['required', 'string', self::ISO3, 'uppercase', Rule::unique('countries', 'alpha3')->ignore($countryId)],
|
||||
'numeric' => ['required', 'string', self::ISO3, Rule::unique('countries', 'numeric')->ignore($countryId)],
|
||||
'name' => ['required', 'string', self::MAX_STRING],
|
||||
'official_name' => ['nullable', 'string', self::MAX_STRING],
|
||||
'common_name' => ['nullable', 'string', self::MAX_STRING],
|
||||
'display_name' => ['nullable', 'string', self::MAX_STRING],
|
||||
'native_name' => ['nullable', 'string', self::MAX_STRING],
|
||||
'capital' => ['nullable', 'string', self::MAX_STRING],
|
||||
'flag_emoji' => ['nullable', 'string', self::MAX_SHORT],
|
||||
'calling_code' => ['nullable', 'string', self::MAX_SHORT],
|
||||
'tld' => ['nullable', 'string', self::MAX_SHORT],
|
||||
'currency_code' => ['nullable', 'string', self::ISO3, 'uppercase'],
|
||||
'currency_name' => ['nullable', 'string', self::MAX_STRING],
|
||||
'currency_symbol' => ['nullable', 'string', self::MAX_SHORT],
|
||||
'languages' => ['nullable', 'json'],
|
||||
'timezones' => ['nullable', 'json'],
|
||||
'latitude' => ['nullable', 'numeric', 'between:-90,90'],
|
||||
'longitude' => ['nullable', 'numeric', 'between:-180,180'],
|
||||
'flag_svg_url' => ['nullable', 'url', 'max:255'],
|
||||
'flag_png_url' => ['nullable', 'url', 'max:255'],
|
||||
'flag_svg_url' => ['nullable', 'url', self::MAX_STRING],
|
||||
'flag_png_url' => ['nullable', 'url', self::MAX_STRING],
|
||||
'ioc_code' => ['nullable', 'string', 'max:8'],
|
||||
'fifa_code' => ['nullable', 'string', 'max:8'],
|
||||
'postal_code_format' => ['nullable', 'string', 'max:255'],
|
||||
'postal_code_format' => ['nullable', 'string', self::MAX_STRING],
|
||||
'address_format' => ['nullable', 'string', 'max:5000'],
|
||||
'is_active' => ['required', 'boolean'],
|
||||
'iso_status' => ['required', 'string', Rule::in(Iso3166::statuses())],
|
||||
@@ -72,10 +78,10 @@ class UpdateCountryRequest extends FormRequest
|
||||
'continent' => ['nullable', 'string', 'max:64'],
|
||||
'region' => ['nullable', 'string', 'max:100'],
|
||||
'subregion' => ['nullable', 'string', 'max:100'],
|
||||
'intermediate_region' => ['nullable', 'string', 'max:255'],
|
||||
'intermediate_region' => ['nullable', 'string', self::MAX_STRING],
|
||||
'sort_order' => ['nullable', 'integer', 'min:0', 'max:999999'],
|
||||
'source' => ['nullable', 'string', 'max:255'],
|
||||
'source_version' => ['nullable', 'string', 'max:255'],
|
||||
'source' => ['nullable', 'string', self::MAX_STRING],
|
||||
'source_version' => ['nullable', 'string', self::MAX_STRING],
|
||||
'last_synced_at' => ['nullable', 'date'],
|
||||
'metadata' => ['nullable', 'json'],
|
||||
];
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
class="overflow-hidden rounded-2xl border border-zinc-200 bg-white shadow-sm dark:border-zinc-700 dark:bg-zinc-900">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-zinc-200 dark:divide-zinc-800">
|
||||
<caption class="sr-only">Data table</caption>
|
||||
<thead class="bg-zinc-50 dark:bg-zinc-950">
|
||||
<tr>
|
||||
<th class="px-4 py-3 text-left text-xs font-bold uppercase tracking-wide text-zinc-500">
|
||||
|
||||
@@ -117,6 +117,7 @@
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-zinc-200 dark:divide-zinc-800">
|
||||
<caption class="sr-only">Data table</caption>
|
||||
<thead class="bg-zinc-50 dark:bg-zinc-950">
|
||||
<tr>
|
||||
<th class="px-4 py-3 text-left text-xs font-bold uppercase tracking-wide text-zinc-500">Area
|
||||
@@ -159,6 +160,7 @@
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-zinc-200 dark:divide-zinc-800">
|
||||
<caption class="sr-only">Data table</caption>
|
||||
<thead class="bg-zinc-50 dark:bg-zinc-950">
|
||||
<tr>
|
||||
<th class="px-4 py-3 text-left text-xs font-bold uppercase tracking-wide text-zinc-500">Code
|
||||
|
||||
@@ -5,6 +5,8 @@ use Modules\Countries\Http\Controllers\CountriesController;
|
||||
use Modules\Countries\Http\Controllers\CountrySyncController;
|
||||
use Modules\Countries\Http\Controllers\ReferenceDataController;
|
||||
|
||||
const COUNTRY_ROUTE = '/{country}';
|
||||
|
||||
Route::prefix('countries')->name('countries.')->middleware(['web', 'auth'])->group(function (): void {
|
||||
Route::get('/', CountriesController::class)->name('index');
|
||||
Route::get('/create', [CountriesController::class, 'create'])->name('create');
|
||||
@@ -15,8 +17,8 @@ Route::prefix('countries')->name('countries.')->middleware(['web', 'auth'])->gro
|
||||
Route::get('/reference/languages', [ReferenceDataController::class, 'languages'])->name('languages.index');
|
||||
Route::get('/reference/scripts', [ReferenceDataController::class, 'scripts'])->name('scripts.index');
|
||||
Route::get('/reference/locodes', [ReferenceDataController::class, 'locodes'])->name('locodes.index');
|
||||
Route::get('/{country:alpha2}', [CountriesController::class, 'show'])->name('show');
|
||||
Route::get('/{country:alpha2}/edit', [CountriesController::class, 'edit'])->name('edit');
|
||||
Route::put('/{country:alpha2}', [CountriesController::class, 'update'])->name('update');
|
||||
Route::delete('/{country:alpha2}', [CountriesController::class, 'destroy'])->name('destroy');
|
||||
Route::get(COUNTRY_ROUTE, [CountriesController::class, 'show'])->name('show');
|
||||
Route::get(COUNTRY_ROUTE . '/edit', [CountriesController::class, 'edit'])->name('edit');
|
||||
Route::put(COUNTRY_ROUTE, [CountriesController::class, 'update'])->name('update');
|
||||
Route::delete(COUNTRY_ROUTE, [CountriesController::class, 'destroy'])->name('destroy');
|
||||
});
|
||||
|
||||
@@ -57,7 +57,7 @@ final class Iso3166
|
||||
{
|
||||
$normalised = str_pad((string) $code, 3, '0', STR_PAD_LEFT);
|
||||
|
||||
if (! preg_match('/^[0-9]{3}$/', $normalised)) {
|
||||
if (! preg_match('/^\d{3}$/', $normalised)) {
|
||||
throw new InvalidArgumentException('ISO 3166-1 numeric codes must contain exactly three digits.');
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<caption class="sr-only">Data table</caption>
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Document</th>
|
||||
|
||||
@@ -15,6 +15,10 @@ use Modules\Documentation\Models\DocumentationDocument;
|
||||
|
||||
class DocumentationController extends Controller
|
||||
{
|
||||
private const string STORAGE_DISK_CONFIG = 'documentation.storage_disk';
|
||||
|
||||
private const string UPLOAD_PATH_CONFIG = 'documentation.upload_path';
|
||||
|
||||
/**
|
||||
* Display the documentation dashboard and document list.
|
||||
*/
|
||||
@@ -170,7 +174,7 @@ class DocumentationController extends Controller
|
||||
{
|
||||
abort_if(blank($document->attachment_path), 404);
|
||||
|
||||
return Storage::disk($document->attachment_disk ?: config('documentation.storage_disk', 'public'))
|
||||
return Storage::disk($document->attachment_disk ?: config(self::STORAGE_DISK_CONFIG, 'public'))
|
||||
->download($document->attachment_path, $document->attachment_name);
|
||||
}
|
||||
|
||||
@@ -202,27 +206,19 @@ class DocumentationController extends Controller
|
||||
*/
|
||||
private function extractMarkdownBody(Request $request): ?string
|
||||
{
|
||||
if (! config('documentation.import_markdown_attachments', true)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$file = $request->file('attachment');
|
||||
$canImport = config('documentation.import_markdown_attachments', true)
|
||||
&& $file !== null
|
||||
&& $this->isMarkdownUpload($request)
|
||||
&& $file->getSize() <= (int) config('documentation.max_markdown_import_bytes', 1048576);
|
||||
|
||||
if ($file === null || ! $this->isMarkdownUpload($request)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($file->getSize() > (int) config('documentation.max_markdown_import_bytes', 1048576)) {
|
||||
if (! $canImport) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$content = file_get_contents($file->getRealPath());
|
||||
|
||||
if ($content === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return trim($content);
|
||||
return $content === false ? null : trim($content);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -250,8 +246,8 @@ class DocumentationController extends Controller
|
||||
private function storeAttachment(Request $request): array
|
||||
{
|
||||
$file = $request->file('attachment');
|
||||
$disk = config('documentation.storage_disk', 'public');
|
||||
$path = $file->store(config('documentation.upload_path', 'documentation'), $disk);
|
||||
$disk = config(self::STORAGE_DISK_CONFIG, 'public');
|
||||
$path = $file->store(config(self::UPLOAD_PATH_CONFIG, 'documentation'), $disk);
|
||||
|
||||
return [
|
||||
'attachment_disk' => $disk,
|
||||
@@ -271,14 +267,14 @@ class DocumentationController extends Controller
|
||||
return;
|
||||
}
|
||||
|
||||
$disk = config('documentation.storage_disk', 'public');
|
||||
$disk = config(self::STORAGE_DISK_CONFIG, 'public');
|
||||
|
||||
foreach ((array) $request->file('attachments') as $file) {
|
||||
if ($file === null || ! $file->isValid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$path = $file->store(config('documentation.upload_path', 'documentation'), $disk);
|
||||
$path = $file->store(config(self::UPLOAD_PATH_CONFIG, 'documentation'), $disk);
|
||||
|
||||
$document->attachments()->create([
|
||||
'disk' => $disk,
|
||||
@@ -297,7 +293,7 @@ class DocumentationController extends Controller
|
||||
private function deleteAttachment(DocumentationDocument $document): void
|
||||
{
|
||||
if (filled($document->attachment_path)) {
|
||||
Storage::disk($document->attachment_disk ?: config('documentation.storage_disk', 'public'))->delete($document->attachment_path);
|
||||
Storage::disk($document->attachment_disk ?: config(self::STORAGE_DISK_CONFIG, 'public'))->delete($document->attachment_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,18 +52,16 @@ class DocumentationAttachment extends Model
|
||||
{
|
||||
$bytes = (int) $this->size;
|
||||
|
||||
$label = number_format($bytes / 1048576, 1) . ' MB';
|
||||
|
||||
if ($bytes <= 0) {
|
||||
return 'Unknown size';
|
||||
$label = 'Unknown size';
|
||||
} elseif ($bytes < 1024) {
|
||||
$label = $bytes . ' B';
|
||||
} elseif ($bytes < 1048576) {
|
||||
$label = number_format($bytes / 1024, 1) . ' KB';
|
||||
}
|
||||
|
||||
if ($bytes < 1024) {
|
||||
return $bytes . ' B';
|
||||
}
|
||||
|
||||
if ($bytes < 1048576) {
|
||||
return number_format($bytes / 1024, 1) . ' KB';
|
||||
}
|
||||
|
||||
return number_format($bytes / 1048576, 1) . ' MB';
|
||||
return $label;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,18 +14,6 @@ class RouteServiceProvider extends ServiceProvider
|
||||
*/
|
||||
protected $moduleNamespace = 'Modules\Documentation\Http\Controllers';
|
||||
|
||||
/**
|
||||
* Called before routes are registered.
|
||||
*
|
||||
* Register any model bindings or pattern based filters.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
parent::boot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the routes for the application.
|
||||
*
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
</div>
|
||||
<div class="doc-card-body">
|
||||
<table class="doc-table">
|
||||
<caption class="sr-only">Data table</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
</form>
|
||||
|
||||
<table class="doc-table">
|
||||
<caption class="sr-only">Data table</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Document</th>
|
||||
|
||||
@@ -6,6 +6,8 @@ use Illuminate\Support\Facades\Route;
|
||||
use Modules\Documentation\Http\Controllers\DocumentationCategoryController;
|
||||
use Modules\Documentation\Http\Controllers\DocumentationController;
|
||||
|
||||
const DOCUMENT_ROUTE = '/documents/{document}';
|
||||
|
||||
Route::middleware(['web', 'auth'])
|
||||
->prefix('documentation')
|
||||
->name('documentation.')
|
||||
@@ -15,13 +17,13 @@ Route::middleware(['web', 'auth'])
|
||||
Route::get('/documents', [DocumentationController::class, 'index'])->name('documents.index');
|
||||
Route::get('/documents/create', [DocumentationController::class, 'create'])->name('documents.create');
|
||||
Route::post('/documents', [DocumentationController::class, 'store'])->name('documents.store');
|
||||
Route::get('/documents/{document}', [DocumentationController::class, 'show'])->name('documents.show');
|
||||
Route::get('/documents/{document}/edit', [DocumentationController::class, 'edit'])->name('documents.edit');
|
||||
Route::put('/documents/{document}', [DocumentationController::class, 'update'])->name('documents.update');
|
||||
Route::delete('/documents/{document}', [DocumentationController::class, 'destroy'])->name('documents.destroy');
|
||||
Route::get('/documents/{document}/download', [DocumentationController::class, 'download'])->name('documents.download');
|
||||
Route::get('/documents/{document}/attachments/{attachment}/download', [DocumentationController::class, 'downloadAttachment'])->name('documents.attachments.download');
|
||||
Route::delete('/documents/{document}/attachments/{attachment}', [DocumentationController::class, 'destroyAttachment'])->name('documents.attachments.destroy');
|
||||
Route::get(DOCUMENT_ROUTE, [DocumentationController::class, 'show'])->name('documents.show');
|
||||
Route::get(DOCUMENT_ROUTE . '/edit', [DocumentationController::class, 'edit'])->name('documents.edit');
|
||||
Route::put(DOCUMENT_ROUTE, [DocumentationController::class, 'update'])->name('documents.update');
|
||||
Route::delete(DOCUMENT_ROUTE, [DocumentationController::class, 'destroy'])->name('documents.destroy');
|
||||
Route::get(DOCUMENT_ROUTE . '/download', [DocumentationController::class, 'download'])->name('documents.download');
|
||||
Route::get(DOCUMENT_ROUTE . '/attachments/{attachment}/download', [DocumentationController::class, 'downloadAttachment'])->name('documents.attachments.download');
|
||||
Route::delete(DOCUMENT_ROUTE . '/attachments/{attachment}', [DocumentationController::class, 'destroyAttachment'])->name('documents.attachments.destroy');
|
||||
|
||||
Route::resource('categories', DocumentationCategoryController::class)->except(['show']);
|
||||
});
|
||||
|
||||
@@ -17,6 +17,8 @@ use Modules\Helpdesk\Models\Ticket;
|
||||
*/
|
||||
final class TicketFactory extends Factory
|
||||
{
|
||||
private const FACTORY_BODY = self::FACTORY_BODY;
|
||||
|
||||
/**
|
||||
* The model name for the factory.
|
||||
*
|
||||
@@ -74,9 +76,9 @@ final class TicketFactory extends Factory
|
||||
$put('reference', 'HD-' . now()->format('Y') . '-' . str_pad((string) $this->faker->unique()->numberBetween(1, 9999), 4, '0', STR_PAD_LEFT));
|
||||
$put('subject', 'Factory helpdesk ticket');
|
||||
$put('title', 'Factory helpdesk ticket');
|
||||
$put('body', '<p>Factory helpdesk ticket body.</p>');
|
||||
$put('details', '<p>Factory helpdesk ticket body.</p>');
|
||||
$put('description', '<p>Factory helpdesk ticket body.</p>');
|
||||
$put('body', self::FACTORY_BODY);
|
||||
$put('details', self::FACTORY_BODY);
|
||||
$put('description', self::FACTORY_BODY);
|
||||
$put('search_text', 'factory helpdesk ticket body');
|
||||
$put('last_activity_at', now());
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\Helpdesk\Exceptions;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
final class TicketPersistenceException extends RuntimeException {}
|
||||
@@ -15,6 +15,20 @@ use Modules\Helpdesk\Services\GitWebhookIngestionService;
|
||||
|
||||
final class GitWebhookController
|
||||
{
|
||||
private const REJECTED = 'rejected';
|
||||
|
||||
private const SIGNATURE_FAILED = 'Git webhook signature or token validation failed.';
|
||||
|
||||
private const SHA256_PREFIX = 'sha256=';
|
||||
|
||||
private const SHA1_PREFIX = 'sha1=';
|
||||
|
||||
private const REQUEST_ID_HEADER = 'X-Request-Id';
|
||||
|
||||
private const GITHUB_DELIVERY_HEADER = 'X-GitHub-Delivery';
|
||||
|
||||
private const GITHUB_EVENT_HEADER = 'X-GitHub-Event';
|
||||
|
||||
/**
|
||||
* Ingest a signed Git provider webhook for a registered Helpdesk repository.
|
||||
*/
|
||||
@@ -24,34 +38,31 @@ final class GitWebhookController
|
||||
$event = $this->eventName($request, $provider);
|
||||
$deliveryId = $this->deliveryId($request, $provider);
|
||||
$rawPayload = $request->getContent();
|
||||
$status = 202;
|
||||
$payload = [];
|
||||
|
||||
if (! $repository->is_active) {
|
||||
$result = ['status' => 'rejected', 'message' => 'Repository is inactive.', 'commit_count' => 0, 'linked_count' => 0, 'ignored_count' => 1];
|
||||
$service->logWebhook($repository, $provider, $deliveryId, $event, $result);
|
||||
|
||||
return response()->json($result, 403);
|
||||
$result = $this->rejectedResult('Repository is inactive.');
|
||||
$status = 403;
|
||||
} elseif (! $this->hasValidSignature($request, $repository, $provider, $rawPayload)) {
|
||||
$result = $this->rejectedResult(self::SIGNATURE_FAILED);
|
||||
$status = 403;
|
||||
} else {
|
||||
try {
|
||||
/** @var array<string, mixed> $payload */
|
||||
$payload = json_decode($rawPayload, true, 512, JSON_THROW_ON_ERROR);
|
||||
$result = $service->ingest($repository, $payload, $provider, $deliveryId, $event);
|
||||
} catch (JsonException) {
|
||||
$result = $this->rejectedResult('Invalid JSON webhook payload.');
|
||||
$status = 400;
|
||||
}
|
||||
}
|
||||
|
||||
if (! $this->hasValidSignature($request, $repository, $provider, $rawPayload)) {
|
||||
$result = ['status' => 'rejected', 'message' => 'Git webhook signature or token validation failed.', 'commit_count' => 0, 'linked_count' => 0, 'ignored_count' => 1];
|
||||
$service->logWebhook($repository, $provider, $deliveryId, $event, $result);
|
||||
|
||||
return response()->json($result, 403);
|
||||
if ($status !== 202) {
|
||||
$service->logWebhook($repository, $provider, $deliveryId, $event, $result, $payload);
|
||||
}
|
||||
|
||||
try {
|
||||
/** @var array<string, mixed> $payload */
|
||||
$payload = json_decode($rawPayload, true, 512, JSON_THROW_ON_ERROR);
|
||||
} catch (JsonException) {
|
||||
$result = ['status' => 'rejected', 'message' => 'Invalid JSON webhook payload.', 'commit_count' => 0, 'linked_count' => 0, 'ignored_count' => 1];
|
||||
$service->logWebhook($repository, $provider, $deliveryId, $event, $result);
|
||||
|
||||
return response()->json($result, 400);
|
||||
}
|
||||
|
||||
$result = $service->ingest($repository, $payload, $provider, $deliveryId, $event);
|
||||
|
||||
return response()->json($result, 202);
|
||||
return response()->json($result, $status);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,42 +74,34 @@ final class GitWebhookController
|
||||
$event = $this->eventName($request, $provider);
|
||||
$deliveryId = $this->deliveryId($request, $provider);
|
||||
$rawPayload = $request->getContent();
|
||||
$status = 202;
|
||||
$repository = null;
|
||||
|
||||
try {
|
||||
/** @var array<string, mixed> $payload */
|
||||
$payload = json_decode($rawPayload, true, 512, JSON_THROW_ON_ERROR);
|
||||
$repository = $this->repositoryForGiteaPayload($payload);
|
||||
|
||||
if (! $repository instanceof GitRepository) {
|
||||
$result = $this->rejectedResult('No active Helpdesk Git repository matched the Gitea webhook payload.');
|
||||
$status = 404;
|
||||
} elseif (! $this->hasValidGiteaSecurity($request, $repository, $provider, $rawPayload)) {
|
||||
$result = $this->rejectedResult(self::SIGNATURE_FAILED);
|
||||
$status = 403;
|
||||
} else {
|
||||
$result = $service->ingest($repository, $payload, $provider, $deliveryId, $event);
|
||||
}
|
||||
} catch (JsonException) {
|
||||
return response()->json([
|
||||
'status' => 'rejected',
|
||||
'message' => 'Invalid JSON webhook payload.',
|
||||
'commit_count' => 0,
|
||||
'linked_count' => 0,
|
||||
'ignored_count' => 1,
|
||||
], 400);
|
||||
$payload = [];
|
||||
$result = $this->rejectedResult('Invalid JSON webhook payload.');
|
||||
$status = 400;
|
||||
}
|
||||
|
||||
$repository = $this->repositoryForGiteaPayload($payload);
|
||||
|
||||
if (! $repository instanceof GitRepository) {
|
||||
return response()->json([
|
||||
'status' => 'rejected',
|
||||
'message' => 'No active Helpdesk Git repository matched the Gitea webhook payload.',
|
||||
'commit_count' => 0,
|
||||
'linked_count' => 0,
|
||||
'ignored_count' => 1,
|
||||
], 404);
|
||||
}
|
||||
|
||||
if (! $this->hasValidGiteaSecurity($request, $repository, $provider, $rawPayload)) {
|
||||
$result = ['status' => 'rejected', 'message' => 'Git webhook signature or token validation failed.', 'commit_count' => 0, 'linked_count' => 0, 'ignored_count' => 1];
|
||||
if ($repository instanceof GitRepository && $status !== 202) {
|
||||
$service->logWebhook($repository, $provider, $deliveryId, $event, $result, $payload);
|
||||
|
||||
return response()->json($result, 403);
|
||||
}
|
||||
|
||||
$result = $service->ingest($repository, $payload, $provider, $deliveryId, $event);
|
||||
|
||||
return response()->json($result, 202);
|
||||
return response()->json($result, $status);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -143,8 +146,8 @@ final class GitWebhookController
|
||||
$sha256Signature = (string) $request->header('X-Hub-Signature-256', '');
|
||||
$sha1Signature = (string) $request->header('X-Hub-Signature', '');
|
||||
|
||||
return hash_equals('sha256=' . hash_hmac('sha256', $rawPayload, $secret), $sha256Signature)
|
||||
|| hash_equals('sha1=' . hash_hmac('sha1', $rawPayload, $secret), $sha1Signature);
|
||||
return hash_equals(self::SHA256_PREFIX . hash_hmac('sha256', $rawPayload, $secret), $sha256Signature)
|
||||
|| hash_equals(self::SHA1_PREFIX . hash_hmac('sha1', $rawPayload, $secret), $sha1Signature);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,8 +161,8 @@ final class GitWebhookController
|
||||
$sha1 = hash_hmac('sha1', $rawPayload, $secret);
|
||||
|
||||
return hash_equals($sha256, $giteaSignature)
|
||||
|| hash_equals('sha256=' . $sha256, $giteaSignature)
|
||||
|| hash_equals('sha1=' . $sha1, $giteaSignature)
|
||||
|| hash_equals(self::SHA256_PREFIX . $sha256, $giteaSignature)
|
||||
|| hash_equals(self::SHA1_PREFIX . $sha1, $giteaSignature)
|
||||
|| $this->hasValidGitHubSignature($request, $secret, $rawPayload)
|
||||
|| $this->hasValidGenericSignature($request, $secret, $rawPayload);
|
||||
}
|
||||
@@ -171,7 +174,7 @@ final class GitWebhookController
|
||||
{
|
||||
$signature = (string) $request->header('X-Hub-Signature', '');
|
||||
|
||||
return hash_equals('sha256=' . hash_hmac('sha256', $rawPayload, $secret), $signature)
|
||||
return hash_equals(self::SHA256_PREFIX . hash_hmac('sha256', $rawPayload, $secret), $signature)
|
||||
|| hash_equals($secret, (string) $request->header('X-Helpdesk-Token', ''));
|
||||
}
|
||||
|
||||
@@ -184,8 +187,8 @@ final class GitWebhookController
|
||||
$signature = (string) ($request->header('X-Hub-Signature-256') ?: $request->header('X-Hub-Signature'));
|
||||
|
||||
return hash_equals($secret, $token)
|
||||
|| hash_equals('sha256=' . hash_hmac('sha256', $rawPayload, $secret), $signature)
|
||||
|| hash_equals('sha1=' . hash_hmac('sha1', $rawPayload, $secret), $signature);
|
||||
|| hash_equals(self::SHA256_PREFIX . hash_hmac('sha256', $rawPayload, $secret), $signature)
|
||||
|| hash_equals(self::SHA1_PREFIX . hash_hmac('sha1', $rawPayload, $secret), $signature);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -230,63 +233,94 @@ final class GitWebhookController
|
||||
->where('is_active', true)
|
||||
->whereRaw('LOWER(provider) IN (?, ?)', ['gitea', 'git'])
|
||||
->get();
|
||||
$matchedRepository = null;
|
||||
|
||||
if ($repositories->isEmpty()) {
|
||||
Log::warning('Helpdesk Gitea webhook received but no active Gitea/git repository is configured.');
|
||||
} else {
|
||||
$normalisedPayloadValues = $this->normalisedPayloadRepositoryValues($payload);
|
||||
$matchedRepository = $repositories->first(
|
||||
fn (GitRepository $repository): bool => $this->repositoryMatchesPayload($repository, $normalisedPayloadValues),
|
||||
);
|
||||
|
||||
return null;
|
||||
if (! $matchedRepository instanceof GitRepository && $repositories->count() === 1) {
|
||||
$matchedRepository = $repositories->first();
|
||||
} elseif (! $matchedRepository instanceof GitRepository) {
|
||||
Log::warning('Helpdesk Gitea webhook did not match any configured repository.', [
|
||||
'payload_repository' => Arr::get($payload, 'repository.full_name') ?: Arr::get($payload, 'repository.clone_url') ?: Arr::get($payload, 'repository.html_url'),
|
||||
'configured_repository_count' => $repositories->count(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$payloadValues = array_values(array_filter([
|
||||
return $matchedRepository instanceof GitRepository ? $matchedRepository : null;
|
||||
}
|
||||
|
||||
/** @param array<string, mixed> $payload
|
||||
* @return list<string>
|
||||
*/
|
||||
private function normalisedPayloadRepositoryValues(array $payload): array
|
||||
{
|
||||
$name = Arr::get($payload, 'repository.name');
|
||||
$owner = Arr::get($payload, 'repository.owner.username');
|
||||
|
||||
return $this->normaliseRepositoryValues([
|
||||
Arr::get($payload, 'repository.full_name'),
|
||||
Arr::get($payload, 'repository.name'),
|
||||
$name,
|
||||
Arr::get($payload, 'repository.html_url'),
|
||||
Arr::get($payload, 'repository.clone_url'),
|
||||
Arr::get($payload, 'repository.ssh_url'),
|
||||
Arr::get($payload, 'repository.url'),
|
||||
Arr::get($payload, 'repository.owner.username') && Arr::get($payload, 'repository.name')
|
||||
? Arr::get($payload, 'repository.owner.username') . '/' . Arr::get($payload, 'repository.name')
|
||||
: null,
|
||||
], static fn (mixed $value): bool => is_scalar($value) && trim((string) $value) !== ''));
|
||||
$owner && $name ? $owner . '/' . $name : null,
|
||||
]);
|
||||
}
|
||||
|
||||
$normalisedPayloadValues = array_values(array_filter(array_map(
|
||||
fn (mixed $value): ?string => $this->normaliseRepositoryIdentity((string) $value),
|
||||
$payloadValues,
|
||||
)));
|
||||
/** @param list<string> $payloadValues */
|
||||
private function repositoryMatchesPayload(GitRepository $repository, array $payloadValues): bool
|
||||
{
|
||||
$repositoryValues = $this->normaliseRepositoryValues([
|
||||
$repository->remote_url,
|
||||
$repository->name,
|
||||
Str::of((string) $repository->remote_url)->afterLast(':')->beforeLast('.git')->value(),
|
||||
]);
|
||||
|
||||
foreach ($repositories as $repository) {
|
||||
$repositoryValues = array_filter([
|
||||
$repository->remote_url,
|
||||
$repository->name,
|
||||
Str::of((string) $repository->remote_url)->afterLast(':')->beforeLast('.git')->value(),
|
||||
], static fn (mixed $value): bool => is_scalar($value) && trim((string) $value) !== '');
|
||||
|
||||
$normalisedRepositoryValues = array_values(array_filter(array_map(
|
||||
fn (mixed $value): ?string => $this->normaliseRepositoryIdentity((string) $value),
|
||||
$repositoryValues,
|
||||
)));
|
||||
|
||||
foreach ($normalisedPayloadValues as $payloadValue) {
|
||||
foreach ($normalisedRepositoryValues as $repositoryValue) {
|
||||
if ($payloadValue === $repositoryValue
|
||||
|| str_ends_with($repositoryValue, '/' . $payloadValue)
|
||||
|| str_ends_with($payloadValue, '/' . $repositoryValue)) {
|
||||
return $repository;
|
||||
}
|
||||
foreach ($payloadValues as $payloadValue) {
|
||||
foreach ($repositoryValues as $repositoryValue) {
|
||||
if ($this->repositoryIdentitiesMatch($payloadValue, $repositoryValue)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($repositories->count() === 1) {
|
||||
return $repositories->first();
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @param array<int, mixed> $values
|
||||
* @return list<string>
|
||||
*/
|
||||
private function normaliseRepositoryValues(array $values): array
|
||||
{
|
||||
$normalised = [];
|
||||
|
||||
foreach ($values as $value) {
|
||||
if (! is_scalar($value) || trim((string) $value) === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$identity = $this->normaliseRepositoryIdentity((string) $value);
|
||||
if ($identity !== null) {
|
||||
$normalised[] = $identity;
|
||||
}
|
||||
}
|
||||
|
||||
Log::warning('Helpdesk Gitea webhook did not match any configured repository.', [
|
||||
'payload_repository' => Arr::get($payload, 'repository.full_name') ?: Arr::get($payload, 'repository.clone_url') ?: Arr::get($payload, 'repository.html_url'),
|
||||
'configured_repository_count' => $repositories->count(),
|
||||
]);
|
||||
return $normalised;
|
||||
}
|
||||
|
||||
return null;
|
||||
private function repositoryIdentitiesMatch(string $payloadValue, string $repositoryValue): bool
|
||||
{
|
||||
return $payloadValue === $repositoryValue
|
||||
|| str_ends_with($repositoryValue, '/' . $payloadValue)
|
||||
|| str_ends_with($payloadValue, '/' . $repositoryValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -325,17 +359,29 @@ final class GitWebhookController
|
||||
return implode('/', array_slice($segments, -2));
|
||||
}
|
||||
|
||||
/** @return array{status: string, message: string, commit_count: int, linked_count: int, ignored_count: int} */
|
||||
private function rejectedResult(string $message): array
|
||||
{
|
||||
return [
|
||||
'status' => self::REJECTED,
|
||||
'message' => $message,
|
||||
'commit_count' => 0,
|
||||
'linked_count' => 0,
|
||||
'ignored_count' => 1,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the event name from provider-specific headers.
|
||||
*/
|
||||
private function eventName(Request $request, string $provider): ?string
|
||||
{
|
||||
return match ($provider) {
|
||||
'github' => $request->header('X-GitHub-Event'),
|
||||
'github' => $request->header(self::GITHUB_EVENT_HEADER),
|
||||
'gitlab' => $request->header('X-Gitlab-Event'),
|
||||
'gitea' => $request->header('X-Gitea-Event') ?: $request->header('X-Gitea-Event-Type') ?: $request->header('X-GitHub-Event'),
|
||||
'gitea' => $request->header('X-Gitea-Event') ?: $request->header('X-Gitea-Event-Type') ?: $request->header(self::GITHUB_EVENT_HEADER),
|
||||
'bitbucket' => $request->header('X-Event-Key'),
|
||||
default => $request->header('X-Helpdesk-Event') ?: $request->header('X-GitHub-Event') ?: $request->header('X-Gitlab-Event') ?: 'push',
|
||||
default => $request->header('X-Helpdesk-Event') ?: $request->header(self::GITHUB_EVENT_HEADER) ?: $request->header('X-Gitlab-Event') ?: 'push',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -345,11 +391,11 @@ final class GitWebhookController
|
||||
private function deliveryId(Request $request, string $provider): ?string
|
||||
{
|
||||
return match ($provider) {
|
||||
'github' => $request->header('X-GitHub-Delivery'),
|
||||
'gitlab' => $request->header('X-Gitlab-Event-UUID') ?: $request->header('X-Request-Id'),
|
||||
'gitea' => $request->header('X-Gitea-Delivery') ?: $request->header('X-GitHub-Delivery') ?: $request->header('X-Request-Id'),
|
||||
'bitbucket' => $request->header('X-Request-UUID') ?: $request->header('X-Request-Id'),
|
||||
default => $request->header('X-Helpdesk-Delivery') ?: $request->header('X-GitHub-Delivery') ?: $request->header('X-Request-Id'),
|
||||
'github' => $request->header(self::GITHUB_DELIVERY_HEADER),
|
||||
'gitlab' => $request->header('X-Gitlab-Event-UUID') ?: $request->header(self::REQUEST_ID_HEADER),
|
||||
'gitea' => $request->header('X-Gitea-Delivery') ?: $request->header(self::GITHUB_DELIVERY_HEADER) ?: $request->header(self::REQUEST_ID_HEADER),
|
||||
'bitbucket' => $request->header('X-Request-UUID') ?: $request->header(self::REQUEST_ID_HEADER),
|
||||
default => $request->header('X-Helpdesk-Delivery') ?: $request->header(self::GITHUB_DELIVERY_HEADER) ?: $request->header(self::REQUEST_ID_HEADER),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Modules\Helpdesk\Exceptions\TicketPersistenceException;
|
||||
use Modules\Helpdesk\Models\KanbanBoard;
|
||||
use Modules\Helpdesk\Models\Status;
|
||||
use Modules\Helpdesk\Models\Ticket;
|
||||
@@ -68,7 +69,7 @@ final class TicketBoardController extends Controller
|
||||
->update($updates);
|
||||
|
||||
if ($affected < 1) {
|
||||
throw new \RuntimeException('Ticket board update did not persist.');
|
||||
throw new TicketPersistenceException('Ticket board update did not persist.');
|
||||
}
|
||||
|
||||
return Ticket::query()
|
||||
|
||||
@@ -25,51 +25,52 @@ final class TicketCommentDeleteController extends Controller
|
||||
abort_unless((int) $comment->ticket_id === (int) $ticket->id, 404);
|
||||
|
||||
DB::transaction(function () use ($comment, $ticket, $user): void {
|
||||
$updates = [];
|
||||
|
||||
if (Schema::hasColumn('helpdesk_comments', 'tombstoned_at')) {
|
||||
$updates['tombstoned_at'] = now();
|
||||
}
|
||||
|
||||
if (Schema::hasColumn('helpdesk_comments', 'deleted_by')) {
|
||||
$updates['deleted_by'] = (int) $user->id;
|
||||
}
|
||||
|
||||
if (Schema::hasColumn('helpdesk_comments', 'delete_reason')) {
|
||||
$updates['delete_reason'] = 'Deleted by MPBA platform administrator.';
|
||||
}
|
||||
|
||||
if (Schema::hasColumn('helpdesk_comments', 'sync_sequence')) {
|
||||
$updates['sync_sequence'] = ((int) ($comment->sync_sequence ?? 0)) + 1;
|
||||
}
|
||||
|
||||
if (Schema::hasColumn('helpdesk_comments', 'sync_hash')) {
|
||||
$updates['sync_hash'] = hash('sha256', implode('|', [
|
||||
(string) ($comment->guid ?? $comment->id),
|
||||
'deleted',
|
||||
now()->toISOString(),
|
||||
]));
|
||||
}
|
||||
|
||||
if (Schema::hasColumn('helpdesk_comments', 'updated_at')) {
|
||||
$updates['updated_at'] = now();
|
||||
}
|
||||
|
||||
if ($updates !== []) {
|
||||
DB::table('helpdesk_comments')
|
||||
->where('id', $comment->id)
|
||||
->update($updates);
|
||||
} else {
|
||||
$comment->delete();
|
||||
}
|
||||
|
||||
if (Schema::hasColumn('helpdesk_tickets', 'last_activity_at')) {
|
||||
$ticket->forceFill(['last_activity_at' => now()])->save();
|
||||
}
|
||||
$this->deleteComment($comment, (int) $user->id);
|
||||
$this->touchTicket($ticket);
|
||||
});
|
||||
|
||||
return redirect()
|
||||
->route('helpdesk.tickets.show', $ticket)
|
||||
->with('ticket-comment-deleted', 'Response deleted.');
|
||||
}
|
||||
|
||||
private function deleteComment(Comment $comment, int $userId): void
|
||||
{
|
||||
$updates = $this->tombstoneUpdates($comment, $userId);
|
||||
|
||||
if ($updates === []) {
|
||||
$comment->delete();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
DB::table('helpdesk_comments')->where('id', $comment->id)->update($updates);
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
private function tombstoneUpdates(Comment $comment, int $userId): array
|
||||
{
|
||||
$now = now();
|
||||
$candidates = [
|
||||
'tombstoned_at' => $now,
|
||||
'deleted_by' => $userId,
|
||||
'delete_reason' => 'Deleted by MPBA platform administrator.',
|
||||
'sync_sequence' => ((int) ($comment->sync_sequence ?? 0)) + 1,
|
||||
'sync_hash' => hash('sha256', implode('|', [(string) ($comment->guid ?? $comment->id), 'deleted', $now->toISOString()])),
|
||||
'updated_at' => $now,
|
||||
];
|
||||
|
||||
return array_filter(
|
||||
$candidates,
|
||||
static fn (mixed $value, string $column): bool => Schema::hasColumn('helpdesk_comments', $column),
|
||||
ARRAY_FILTER_USE_BOTH,
|
||||
);
|
||||
}
|
||||
|
||||
private function touchTicket(Ticket $ticket): void
|
||||
{
|
||||
if (Schema::hasColumn('helpdesk_tickets', 'last_activity_at')) {
|
||||
$ticket->forceFill(['last_activity_at' => now()])->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,62 +35,71 @@ final class TicketTimeLogController extends Controller
|
||||
$loggedAt = now();
|
||||
|
||||
DB::transaction(function () use ($ticket, $request, $minutes, $description, $loggedAt): void {
|
||||
if (Schema::hasColumn($ticket->getTable(), 'time_spent_minutes')) {
|
||||
$ticket->increment('time_spent_minutes', $minutes, [
|
||||
'last_activity_at' => $loggedAt,
|
||||
]);
|
||||
} elseif (Schema::hasColumn($ticket->getTable(), 'last_activity_at')) {
|
||||
$ticket->forceFill(['last_activity_at' => $loggedAt])->save();
|
||||
}
|
||||
|
||||
if (Schema::hasTable('helpdesk_time_logs')) {
|
||||
DB::table('helpdesk_time_logs')->insert([
|
||||
'ticket_id' => $ticket->getKey(),
|
||||
'user_id' => $request->user()->getKey(),
|
||||
'minutes' => $minutes,
|
||||
'description' => $description,
|
||||
'logged_at' => $loggedAt,
|
||||
'created_at' => $loggedAt,
|
||||
'updated_at' => $loggedAt,
|
||||
]);
|
||||
}
|
||||
|
||||
if (Schema::hasTable('helpdesk_ticket_time_logs')) {
|
||||
$payload = [
|
||||
'ticket_id' => $ticket->getKey(),
|
||||
'user_id' => $request->user()->getKey(),
|
||||
'minutes' => $minutes,
|
||||
'description' => $description,
|
||||
'created_at' => $loggedAt,
|
||||
'updated_at' => $loggedAt,
|
||||
];
|
||||
|
||||
if (Schema::hasColumn('helpdesk_ticket_time_logs', 'started_at')) {
|
||||
$payload['started_at'] = $loggedAt->copy()->subMinutes($minutes);
|
||||
}
|
||||
|
||||
if (Schema::hasColumn('helpdesk_ticket_time_logs', 'ended_at')) {
|
||||
$payload['ended_at'] = $loggedAt;
|
||||
}
|
||||
|
||||
if (Schema::hasColumn('helpdesk_ticket_time_logs', 'logged_at')) {
|
||||
$payload['logged_at'] = $loggedAt;
|
||||
}
|
||||
|
||||
if (Schema::hasColumn('helpdesk_ticket_time_logs', 'duration_seconds')) {
|
||||
$payload['duration_seconds'] = $minutes * 60;
|
||||
}
|
||||
|
||||
if (Schema::hasColumn('helpdesk_ticket_time_logs', 'seconds')) {
|
||||
$payload['seconds'] = $minutes * 60;
|
||||
}
|
||||
|
||||
DB::table('helpdesk_ticket_time_logs')->insert($payload);
|
||||
}
|
||||
$this->updateTicketActivity($ticket, $minutes, $loggedAt);
|
||||
$this->storeLegacyTimeLog($ticket, $request, $minutes, $description, $loggedAt);
|
||||
$this->storeTicketTimeLog($ticket, $request, $minutes, $description, $loggedAt);
|
||||
});
|
||||
|
||||
return redirect()
|
||||
->route('helpdesk.tickets.show', $ticket)
|
||||
->with('ticket-action-updated', 'Time logged successfully.');
|
||||
}
|
||||
|
||||
private function updateTicketActivity(Ticket $ticket, int $minutes, $loggedAt): void
|
||||
{
|
||||
if (Schema::hasColumn($ticket->getTable(), 'time_spent_minutes')) {
|
||||
$ticket->increment('time_spent_minutes', $minutes, ['last_activity_at' => $loggedAt]);
|
||||
} elseif (Schema::hasColumn($ticket->getTable(), 'last_activity_at')) {
|
||||
$ticket->forceFill(['last_activity_at' => $loggedAt])->save();
|
||||
}
|
||||
}
|
||||
|
||||
private function storeLegacyTimeLog(Ticket $ticket, Request $request, int $minutes, ?string $description, $loggedAt): void
|
||||
{
|
||||
if (! Schema::hasTable('helpdesk_time_logs')) {
|
||||
return;
|
||||
}
|
||||
|
||||
DB::table('helpdesk_time_logs')->insert([
|
||||
'ticket_id' => $ticket->getKey(),
|
||||
'user_id' => $request->user()->getKey(),
|
||||
'minutes' => $minutes,
|
||||
'description' => $description,
|
||||
'logged_at' => $loggedAt,
|
||||
'created_at' => $loggedAt,
|
||||
'updated_at' => $loggedAt,
|
||||
]);
|
||||
}
|
||||
|
||||
private function storeTicketTimeLog(Ticket $ticket, Request $request, int $minutes, ?string $description, $loggedAt): void
|
||||
{
|
||||
if (! Schema::hasTable('helpdesk_ticket_time_logs')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$payload = [
|
||||
'ticket_id' => $ticket->getKey(),
|
||||
'user_id' => $request->user()->getKey(),
|
||||
'minutes' => $minutes,
|
||||
'description' => $description,
|
||||
'created_at' => $loggedAt,
|
||||
'updated_at' => $loggedAt,
|
||||
];
|
||||
|
||||
$optional = [
|
||||
'started_at' => $loggedAt->copy()->subMinutes($minutes),
|
||||
'ended_at' => $loggedAt,
|
||||
'logged_at' => $loggedAt,
|
||||
'duration_seconds' => $minutes * 60,
|
||||
'seconds' => $minutes * 60,
|
||||
];
|
||||
|
||||
foreach ($optional as $column => $value) {
|
||||
if (Schema::hasColumn('helpdesk_ticket_time_logs', $column)) {
|
||||
$payload[$column] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
DB::table('helpdesk_ticket_time_logs')->insert($payload);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ use Modules\Helpdesk\Services\WorkflowNotificationService;
|
||||
|
||||
final class KanbanBoard extends Component
|
||||
{
|
||||
private const OWNER_RELATION = self::OWNER_RELATION;
|
||||
|
||||
public ?int $board_id = null;
|
||||
|
||||
public int $refreshNonce = 0;
|
||||
@@ -98,7 +100,7 @@ final class KanbanBoard extends Component
|
||||
public function moveTicketToBoard(int|string $ticketId, int|string|null $boardId, WorkflowNotificationService $workflow): void
|
||||
{
|
||||
$ticket = Ticket::query()->with('board')->visibleTo(Auth::user())->findOrFail((int) $ticketId);
|
||||
$board = KanbanBoardModel::query()->with(['statuses', 'owner:id,name,email'])->findOrFail((int) $boardId);
|
||||
$board = KanbanBoardModel::query()->with(['statuses', self::OWNER_RELATION])->findOrFail((int) $boardId);
|
||||
$oldBoardName = $ticket->board?->name ?? 'No board';
|
||||
|
||||
$this->authorize('update', $ticket);
|
||||
@@ -156,8 +158,7 @@ final class KanbanBoard extends Component
|
||||
*/
|
||||
public function selectBoard(int|string|null $value): void
|
||||
{
|
||||
$this->board_id = is_numeric($value) ? (int) $value : null;
|
||||
$this->refreshBoard();
|
||||
$this->updatedBoardId($value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -166,7 +167,7 @@ final class KanbanBoard extends Component
|
||||
public function render(): View
|
||||
{
|
||||
$boards = KanbanBoardModel::query()
|
||||
->with(['statuses', 'owner:id,name,email'])
|
||||
->with(['statuses', self::OWNER_RELATION])
|
||||
->orderBy('sort_order')
|
||||
->orderBy('name')
|
||||
->get();
|
||||
@@ -176,10 +177,10 @@ final class KanbanBoard extends Component
|
||||
|
||||
if ($board instanceof KanbanBoardModel && $board->statuses->isEmpty()) {
|
||||
$this->ensureBoardHasStatuses($board);
|
||||
$board->load(['statuses', 'owner:id,name,email']);
|
||||
$board->load(['statuses', self::OWNER_RELATION]);
|
||||
|
||||
$boards = KanbanBoardModel::query()
|
||||
->with(['statuses', 'owner:id,name,email'])
|
||||
->with(['statuses', self::OWNER_RELATION])
|
||||
->orderBy('sort_order')
|
||||
->orderBy('name')
|
||||
->get();
|
||||
@@ -206,7 +207,7 @@ final class KanbanBoard extends Component
|
||||
}
|
||||
|
||||
return Ticket::query()
|
||||
->with(['user:id,name,email', 'owner:id,name,email', 'agent:id,name,email', 'status', 'priority', 'category', 'project', 'team', 'product', 'tags', 'checklistItems', 'board'])
|
||||
->with(['user:id,name,email', self::OWNER_RELATION, 'agent:id,name,email', 'status', 'priority', 'category', 'project', 'team', 'product', 'tags', 'checklistItems', 'board'])
|
||||
->visibleTo(Auth::user())
|
||||
->where('board_id', $board->id)
|
||||
->latest('last_activity_at')
|
||||
|
||||
@@ -31,6 +31,30 @@ use Modules\Helpdesk\Support\Color;
|
||||
|
||||
final class SettingsManager extends Component
|
||||
{
|
||||
private const RULE_MAX_40 = 'max:40';
|
||||
|
||||
private const RULE_MAX_80 = 'max:80';
|
||||
|
||||
private const RULE_MAX_100 = 'max:100';
|
||||
|
||||
private const RULE_MAX_120 = 'max:120';
|
||||
|
||||
private const RULE_MAX_160 = 'max:160';
|
||||
|
||||
private const RULE_MAX_180 = 'max:180';
|
||||
|
||||
private const RULE_MAX_220 = 'max:220';
|
||||
|
||||
private const RULE_MAX_500 = 'max:500';
|
||||
|
||||
private const RULE_MIN_0 = 'min:0';
|
||||
|
||||
private const RULE_TEAM_EXISTS = 'exists:helpdesk_teams,id';
|
||||
|
||||
private const RULE_PROJECT_EXISTS = 'exists:helpdesk_projects,id';
|
||||
|
||||
private const RULE_CATEGORY_EXISTS = 'exists:helpdesk_categories,id';
|
||||
|
||||
public string $section = 'statuses';
|
||||
|
||||
public int|string|null $default_helpdesk_company_id = null;
|
||||
@@ -126,10 +150,10 @@ final class SettingsManager extends Component
|
||||
public function saveStatus(): void
|
||||
{
|
||||
$data = $this->validate([
|
||||
'statusForm.name' => ['required', 'string', 'max:80'],
|
||||
'statusForm.slug' => ['nullable', 'string', 'max:100'],
|
||||
'statusForm.name' => ['required', 'string', self::RULE_MAX_80],
|
||||
'statusForm.slug' => ['nullable', 'string', self::RULE_MAX_100],
|
||||
'statusForm.color' => ['required', 'string', Color::validationRule()],
|
||||
'statusForm.sort_order' => ['required', 'integer', 'min:0'],
|
||||
'statusForm.sort_order' => ['required', 'integer', self::RULE_MIN_0],
|
||||
'statusForm.is_closed' => ['boolean'],
|
||||
'statusForm.is_default' => ['boolean'],
|
||||
])['statusForm'];
|
||||
@@ -167,10 +191,10 @@ final class SettingsManager extends Component
|
||||
public function savePriority(): void
|
||||
{
|
||||
$data = $this->validate([
|
||||
'priorityForm.name' => ['required', 'string', 'max:80'],
|
||||
'priorityForm.slug' => ['nullable', 'string', 'max:100'],
|
||||
'priorityForm.name' => ['required', 'string', self::RULE_MAX_80],
|
||||
'priorityForm.slug' => ['nullable', 'string', self::RULE_MAX_100],
|
||||
'priorityForm.color' => ['required', 'string', Color::validationRule()],
|
||||
'priorityForm.sort_order' => ['required', 'integer', 'min:0'],
|
||||
'priorityForm.sort_order' => ['required', 'integer', self::RULE_MIN_0],
|
||||
'priorityForm.is_default' => ['boolean'],
|
||||
])['priorityForm'];
|
||||
|
||||
@@ -209,7 +233,7 @@ final class SettingsManager extends Component
|
||||
|
||||
$data = $this->validate([
|
||||
'categoryForm.company_id' => ['nullable', 'integer'],
|
||||
'categoryForm.name' => ['required', 'string', 'max:120'],
|
||||
'categoryForm.name' => ['required', 'string', self::RULE_MAX_120],
|
||||
'categoryForm.slug' => ['nullable', 'string', 'max:140'],
|
||||
'categoryForm.color' => ['required', 'string', Color::validationRule()],
|
||||
'categoryForm.description' => ['nullable', 'string'],
|
||||
@@ -251,7 +275,7 @@ final class SettingsManager extends Component
|
||||
|
||||
$data = $this->validate([
|
||||
'teamForm.company_id' => ['nullable', 'integer'],
|
||||
'teamForm.name' => ['required', 'string', 'max:120'],
|
||||
'teamForm.name' => ['required', 'string', self::RULE_MAX_120],
|
||||
'teamForm.slug' => ['nullable', 'string', 'max:140'],
|
||||
'teamForm.color' => ['required', 'string', Color::validationRule()],
|
||||
'teamForm.description' => ['nullable', 'string'],
|
||||
@@ -293,9 +317,9 @@ final class SettingsManager extends Component
|
||||
|
||||
$data = $this->validate([
|
||||
'projectForm.company_id' => ['nullable', 'integer'],
|
||||
'projectForm.team_id' => ['nullable', 'integer', 'exists:helpdesk_teams,id'],
|
||||
'projectForm.title' => ['required', 'string', 'max:160'],
|
||||
'projectForm.slug' => ['nullable', 'string', 'max:180'],
|
||||
'projectForm.team_id' => ['nullable', 'integer', self::RULE_TEAM_EXISTS],
|
||||
'projectForm.title' => ['required', 'string', self::RULE_MAX_160],
|
||||
'projectForm.slug' => ['nullable', 'string', self::RULE_MAX_180],
|
||||
'projectForm.color' => ['required', 'string', Color::validationRule()],
|
||||
'projectForm.description' => ['nullable', 'string'],
|
||||
'projectForm.is_default' => ['boolean'],
|
||||
@@ -335,12 +359,12 @@ final class SettingsManager extends Component
|
||||
$this->normalizeNullableFormValues('boardForm', ['owner_id']);
|
||||
|
||||
$data = $this->validate([
|
||||
'boardForm.name' => ['required', 'string', 'max:160'],
|
||||
'boardForm.slug' => ['nullable', 'string', 'max:180'],
|
||||
'boardForm.name' => ['required', 'string', self::RULE_MAX_160],
|
||||
'boardForm.slug' => ['nullable', 'string', self::RULE_MAX_180],
|
||||
'boardForm.description' => ['nullable', 'string'],
|
||||
'boardForm.owner_id' => ['nullable', 'integer', 'exists:users,id'],
|
||||
'boardForm.is_default' => ['boolean'],
|
||||
'boardForm.sort_order' => ['required', 'integer', 'min:0'],
|
||||
'boardForm.sort_order' => ['required', 'integer', self::RULE_MIN_0],
|
||||
'boardForm.status_ids' => ['array'],
|
||||
'boardForm.status_ids.*' => ['integer', 'exists:helpdesk_statuses,id'],
|
||||
])['boardForm'];
|
||||
@@ -403,12 +427,12 @@ final class SettingsManager extends Component
|
||||
|
||||
$data = $this->validate([
|
||||
'repositoryForm.company_id' => ['nullable', 'integer'],
|
||||
'repositoryForm.project_id' => ['nullable', 'integer', 'exists:helpdesk_projects,id'],
|
||||
'repositoryForm.name' => ['required', 'string', 'max:160'],
|
||||
'repositoryForm.provider' => ['required', 'string', 'max:40'],
|
||||
'repositoryForm.remote_url' => ['required', 'string', 'max:500'],
|
||||
'repositoryForm.default_branch' => ['required', 'string', 'max:120'],
|
||||
'repositoryForm.webhook_secret' => ['nullable', 'string', 'max:120'],
|
||||
'repositoryForm.project_id' => ['nullable', 'integer', self::RULE_PROJECT_EXISTS],
|
||||
'repositoryForm.name' => ['required', 'string', self::RULE_MAX_160],
|
||||
'repositoryForm.provider' => ['required', 'string', self::RULE_MAX_40],
|
||||
'repositoryForm.remote_url' => ['required', 'string', self::RULE_MAX_500],
|
||||
'repositoryForm.default_branch' => ['required', 'string', self::RULE_MAX_120],
|
||||
'repositoryForm.webhook_secret' => ['nullable', 'string', self::RULE_MAX_120],
|
||||
])['repositoryForm'];
|
||||
|
||||
$data['provider'] = strtolower(trim((string) $data['provider']));
|
||||
@@ -440,14 +464,14 @@ final class SettingsManager extends Component
|
||||
$this->normalizeNullableFormValues('workflowForm', ['text_body', 'cc', 'bcc']);
|
||||
|
||||
$data = $this->validate([
|
||||
'workflowForm.name' => ['required', 'string', 'max:160'],
|
||||
'workflowForm.event' => ['required', 'string', 'max:80'],
|
||||
'workflowForm.subject' => ['required', 'string', 'max:220'],
|
||||
'workflowForm.name' => ['required', 'string', self::RULE_MAX_160],
|
||||
'workflowForm.event' => ['required', 'string', self::RULE_MAX_80],
|
||||
'workflowForm.subject' => ['required', 'string', self::RULE_MAX_220],
|
||||
'workflowForm.html_body' => ['required', 'string'],
|
||||
'workflowForm.text_body' => ['nullable', 'string'],
|
||||
'workflowForm.to_role' => ['required', 'string', 'max:40'],
|
||||
'workflowForm.cc' => ['nullable', 'string', 'max:500'],
|
||||
'workflowForm.bcc' => ['nullable', 'string', 'max:500'],
|
||||
'workflowForm.to_role' => ['required', 'string', self::RULE_MAX_40],
|
||||
'workflowForm.cc' => ['nullable', 'string', self::RULE_MAX_500],
|
||||
'workflowForm.bcc' => ['nullable', 'string', self::RULE_MAX_500],
|
||||
'workflowForm.is_active' => ['boolean'],
|
||||
])['workflowForm'];
|
||||
|
||||
@@ -479,15 +503,15 @@ final class SettingsManager extends Component
|
||||
|
||||
$data = $this->validate([
|
||||
'cannedForm.company_id' => ['nullable', 'integer'],
|
||||
'cannedForm.category_id' => ['nullable', 'integer', 'exists:helpdesk_categories,id'],
|
||||
'cannedForm.team_id' => ['nullable', 'integer', 'exists:helpdesk_teams,id'],
|
||||
'cannedForm.name' => ['required', 'string', 'max:160'],
|
||||
'cannedForm.slug' => ['nullable', 'string', 'max:180'],
|
||||
'cannedForm.visibility' => ['required', 'string', 'max:40'],
|
||||
'cannedForm.subject' => ['nullable', 'string', 'max:220'],
|
||||
'cannedForm.category_id' => ['nullable', 'integer', self::RULE_CATEGORY_EXISTS],
|
||||
'cannedForm.team_id' => ['nullable', 'integer', self::RULE_TEAM_EXISTS],
|
||||
'cannedForm.name' => ['required', 'string', self::RULE_MAX_160],
|
||||
'cannedForm.slug' => ['nullable', 'string', self::RULE_MAX_180],
|
||||
'cannedForm.visibility' => ['required', 'string', self::RULE_MAX_40],
|
||||
'cannedForm.subject' => ['nullable', 'string', self::RULE_MAX_220],
|
||||
'cannedForm.body' => ['required', 'string'],
|
||||
'cannedForm.is_active' => ['boolean'],
|
||||
'cannedForm.sort_order' => ['required', 'integer', 'min:0'],
|
||||
'cannedForm.sort_order' => ['required', 'integer', self::RULE_MIN_0],
|
||||
])['cannedForm'];
|
||||
$data['slug'] = $this->slug($data['slug'] ?: $data['name']);
|
||||
$this->persistSettingModel(CannedResponse::class, $this->cannedForm['id'], $data);
|
||||
@@ -519,9 +543,9 @@ final class SettingsManager extends Component
|
||||
$data = $this->validate([
|
||||
'slaForm.company_id' => ['nullable', 'integer'],
|
||||
'slaForm.priority_id' => ['nullable', 'integer', 'exists:helpdesk_priorities,id'],
|
||||
'slaForm.category_id' => ['nullable', 'integer', 'exists:helpdesk_categories,id'],
|
||||
'slaForm.name' => ['required', 'string', 'max:160'],
|
||||
'slaForm.slug' => ['nullable', 'string', 'max:180'],
|
||||
'slaForm.category_id' => ['nullable', 'integer', self::RULE_CATEGORY_EXISTS],
|
||||
'slaForm.name' => ['required', 'string', self::RULE_MAX_160],
|
||||
'slaForm.slug' => ['nullable', 'string', self::RULE_MAX_180],
|
||||
'slaForm.first_response_minutes' => ['required', 'integer', 'min:1'],
|
||||
'slaForm.resolution_minutes' => ['required', 'integer', 'min:1'],
|
||||
'slaForm.business_hours_only' => ['boolean'],
|
||||
@@ -560,20 +584,20 @@ final class SettingsManager extends Component
|
||||
|
||||
$data = $this->validate([
|
||||
'automationForm.company_id' => ['nullable', 'integer'],
|
||||
'automationForm.name' => ['required', 'string', 'max:160'],
|
||||
'automationForm.slug' => ['nullable', 'string', 'max:180'],
|
||||
'automationForm.name' => ['required', 'string', self::RULE_MAX_160],
|
||||
'automationForm.slug' => ['nullable', 'string', self::RULE_MAX_180],
|
||||
'automationForm.match_sender' => ['nullable', 'string', 'max:190'],
|
||||
'automationForm.match_subject' => ['nullable', 'string', 'max:220'],
|
||||
'automationForm.match_subject' => ['nullable', 'string', self::RULE_MAX_220],
|
||||
'automationForm.match_mailbox' => ['nullable', 'string', 'max:190'],
|
||||
'automationForm.match_category_id' => ['nullable', 'integer', 'exists:helpdesk_categories,id'],
|
||||
'automationForm.match_category_id' => ['nullable', 'integer', self::RULE_CATEGORY_EXISTS],
|
||||
'automationForm.set_priority_id' => ['nullable', 'integer', 'exists:helpdesk_priorities,id'],
|
||||
'automationForm.set_category_id' => ['nullable', 'integer', 'exists:helpdesk_categories,id'],
|
||||
'automationForm.set_team_id' => ['nullable', 'integer', 'exists:helpdesk_teams,id'],
|
||||
'automationForm.set_project_id' => ['nullable', 'integer', 'exists:helpdesk_projects,id'],
|
||||
'automationForm.set_category_id' => ['nullable', 'integer', self::RULE_CATEGORY_EXISTS],
|
||||
'automationForm.set_team_id' => ['nullable', 'integer', self::RULE_TEAM_EXISTS],
|
||||
'automationForm.set_project_id' => ['nullable', 'integer', self::RULE_PROJECT_EXISTS],
|
||||
'automationForm.set_status_id' => ['nullable', 'integer', 'exists:helpdesk_statuses,id'],
|
||||
'automationForm.set_agent_id' => ['nullable', 'integer', 'exists:users,id'],
|
||||
'automationForm.is_active' => ['boolean'],
|
||||
'automationForm.sort_order' => ['required', 'integer', 'min:0'],
|
||||
'automationForm.sort_order' => ['required', 'integer', self::RULE_MIN_0],
|
||||
])['automationForm'];
|
||||
$data['slug'] = $this->slug($data['slug'] ?: $data['name']);
|
||||
$this->persistSettingModel(AutomationRule::class, $this->automationForm['id'], $data);
|
||||
@@ -604,11 +628,11 @@ final class SettingsManager extends Component
|
||||
|
||||
$data = $this->validate([
|
||||
'productForm.company_id' => ['nullable', 'integer'],
|
||||
'productForm.name' => ['required', 'string', 'max:160'],
|
||||
'productForm.slug' => ['nullable', 'string', 'max:180'],
|
||||
'productForm.name' => ['required', 'string', self::RULE_MAX_160],
|
||||
'productForm.slug' => ['nullable', 'string', self::RULE_MAX_180],
|
||||
'productForm.type' => ['required', 'string', 'max:60'],
|
||||
'productForm.version' => ['nullable', 'string', 'max:80'],
|
||||
'productForm.release_channel' => ['nullable', 'string', 'max:80'],
|
||||
'productForm.version' => ['nullable', 'string', self::RULE_MAX_80],
|
||||
'productForm.release_channel' => ['nullable', 'string', self::RULE_MAX_80],
|
||||
'productForm.description' => ['nullable', 'string'],
|
||||
'productForm.is_active' => ['boolean'],
|
||||
])['productForm'];
|
||||
@@ -641,8 +665,8 @@ final class SettingsManager extends Component
|
||||
|
||||
$data = $this->validate([
|
||||
'tagForm.company_id' => ['nullable', 'integer'],
|
||||
'tagForm.name' => ['required', 'string', 'max:80'],
|
||||
'tagForm.slug' => ['nullable', 'string', 'max:100'],
|
||||
'tagForm.name' => ['required', 'string', self::RULE_MAX_80],
|
||||
'tagForm.slug' => ['nullable', 'string', self::RULE_MAX_100],
|
||||
'tagForm.color' => ['required', 'string', Color::validationRule()],
|
||||
])['tagForm'];
|
||||
$data['slug'] = $this->slug($data['slug'] ?: $data['name']);
|
||||
@@ -675,10 +699,10 @@ final class SettingsManager extends Component
|
||||
|
||||
$data = $this->validate([
|
||||
'checklistTemplateForm.company_id' => ['nullable', 'integer'],
|
||||
'checklistTemplateForm.category_id' => ['nullable', 'integer', 'exists:helpdesk_categories,id'],
|
||||
'checklistTemplateForm.project_id' => ['nullable', 'integer', 'exists:helpdesk_projects,id'],
|
||||
'checklistTemplateForm.name' => ['required', 'string', 'max:160'],
|
||||
'checklistTemplateForm.slug' => ['nullable', 'string', 'max:180'],
|
||||
'checklistTemplateForm.category_id' => ['nullable', 'integer', self::RULE_CATEGORY_EXISTS],
|
||||
'checklistTemplateForm.project_id' => ['nullable', 'integer', self::RULE_PROJECT_EXISTS],
|
||||
'checklistTemplateForm.name' => ['required', 'string', self::RULE_MAX_160],
|
||||
'checklistTemplateForm.slug' => ['nullable', 'string', self::RULE_MAX_180],
|
||||
'checklistTemplateForm.items_text' => ['required', 'string'],
|
||||
'checklistTemplateForm.is_active' => ['boolean'],
|
||||
])['checklistTemplateForm'];
|
||||
@@ -855,10 +879,8 @@ final class SettingsManager extends Component
|
||||
return $model;
|
||||
}
|
||||
|
||||
/** @var TModel $model */
|
||||
$model = $modelClass::query()->create($data);
|
||||
|
||||
return $model;
|
||||
/** @var TModel */
|
||||
return $modelClass::query()->create($data);
|
||||
} catch (QueryException $exception) {
|
||||
throw ValidationException::withMessages([
|
||||
'settings' => 'The record could not be saved. Check the slug is unique for this section/company and try again.',
|
||||
|
||||
@@ -22,6 +22,8 @@ use Modules\Helpdesk\Services\TicketService;
|
||||
|
||||
final class TicketCreate extends Component
|
||||
{
|
||||
private const COMPANY_NULL_ORDER = 'company_id is null';
|
||||
|
||||
use WithFileUploads;
|
||||
|
||||
public ?int $company_id = null;
|
||||
@@ -188,7 +190,7 @@ final class TicketCreate extends Component
|
||||
$query->where('company_id', $this->company_id)
|
||||
->orWhereNull('company_id');
|
||||
}))
|
||||
->orderByRaw('company_id is null')
|
||||
->orderByRaw(self::COMPANY_NULL_ORDER)
|
||||
->orderBy('name')
|
||||
->value('id');
|
||||
}
|
||||
@@ -201,7 +203,7 @@ final class TicketCreate extends Component
|
||||
$query->where('company_id', $this->company_id)
|
||||
->orWhereNull('company_id');
|
||||
}))
|
||||
->orderByRaw('company_id is null')
|
||||
->orderByRaw(self::COMPANY_NULL_ORDER)
|
||||
->orderBy('name')
|
||||
->value('id');
|
||||
}
|
||||
@@ -218,7 +220,7 @@ final class TicketCreate extends Component
|
||||
$query->where('team_id', $this->team_id)
|
||||
->orWhereNull('team_id');
|
||||
}))
|
||||
->orderByRaw('company_id is null')
|
||||
->orderByRaw(self::COMPANY_NULL_ORDER)
|
||||
->orderByRaw('team_id is null')
|
||||
->orderBy('title')
|
||||
->value('id');
|
||||
|
||||
@@ -515,19 +515,17 @@ final class TicketShow extends Component
|
||||
*/
|
||||
public function firstResponseSlaClasses(): string
|
||||
{
|
||||
$classes = 'border-blue-200 bg-blue-50 text-blue-900 dark:border-blue-900 dark:bg-blue-950 dark:text-blue-100';
|
||||
|
||||
if ($this->firstResponseWasBreached()) {
|
||||
return 'border-red-300 bg-red-50 text-red-900 dark:border-red-900 dark:bg-red-950 dark:text-red-100';
|
||||
$classes = 'border-red-300 bg-red-50 text-red-900 dark:border-red-900 dark:bg-red-950 dark:text-red-100';
|
||||
} elseif ($this->ticket->first_response_at !== null) {
|
||||
$classes = 'border-emerald-200 bg-emerald-50 text-emerald-900 dark:border-emerald-900 dark:bg-emerald-950 dark:text-emerald-100';
|
||||
} elseif ($this->firstResponseIsDueSoon()) {
|
||||
$classes = 'border-amber-300 bg-amber-50 text-amber-950 dark:border-amber-900 dark:bg-amber-950 dark:text-amber-100';
|
||||
}
|
||||
|
||||
if ($this->ticket->first_response_at !== null) {
|
||||
return 'border-emerald-200 bg-emerald-50 text-emerald-900 dark:border-emerald-900 dark:bg-emerald-950 dark:text-emerald-100';
|
||||
}
|
||||
|
||||
if ($this->firstResponseIsDueSoon()) {
|
||||
return 'border-amber-300 bg-amber-50 text-amber-950 dark:border-amber-900 dark:bg-amber-950 dark:text-amber-100';
|
||||
}
|
||||
|
||||
return 'border-blue-200 bg-blue-50 text-blue-900 dark:border-blue-900 dark:bg-blue-950 dark:text-blue-100';
|
||||
return $classes;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -567,19 +565,17 @@ final class TicketShow extends Component
|
||||
*/
|
||||
public function resolutionSlaClasses(): string
|
||||
{
|
||||
$classes = 'border-blue-200 bg-blue-50 text-blue-900 dark:border-blue-900 dark:bg-blue-950 dark:text-blue-100';
|
||||
|
||||
if ($this->resolutionWasBreached()) {
|
||||
return 'border-red-300 bg-red-50 text-red-900 dark:border-red-900 dark:bg-red-950 dark:text-red-100';
|
||||
$classes = 'border-red-300 bg-red-50 text-red-900 dark:border-red-900 dark:bg-red-950 dark:text-red-100';
|
||||
} elseif ($this->ticket->completed_at !== null) {
|
||||
$classes = 'border-emerald-200 bg-emerald-50 text-emerald-900 dark:border-emerald-900 dark:bg-emerald-950 dark:text-emerald-100';
|
||||
} elseif ($this->resolutionIsDueSoon()) {
|
||||
$classes = 'border-amber-300 bg-amber-50 text-amber-950 dark:border-amber-900 dark:bg-amber-950 dark:text-amber-100';
|
||||
}
|
||||
|
||||
if ($this->ticket->completed_at !== null) {
|
||||
return 'border-emerald-200 bg-emerald-50 text-emerald-900 dark:border-emerald-900 dark:bg-emerald-950 dark:text-emerald-100';
|
||||
}
|
||||
|
||||
if ($this->resolutionIsDueSoon()) {
|
||||
return 'border-amber-300 bg-amber-50 text-amber-950 dark:border-amber-900 dark:bg-amber-950 dark:text-amber-100';
|
||||
}
|
||||
|
||||
return 'border-blue-200 bg-blue-50 text-blue-900 dark:border-blue-900 dark:bg-blue-950 dark:text-blue-100';
|
||||
return $classes;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -774,12 +770,6 @@ final class TicketShow extends Component
|
||||
/**
|
||||
* Add a case-insensitive LIKE condition that works on PostgreSQL and SQLite tests.
|
||||
*/
|
||||
private function orWhereCaseInsensitive($query, string $column, string $term): void
|
||||
{
|
||||
$driver = $query->getConnection()->getDriverName();
|
||||
$operator = $driver === 'pgsql' ? $this->gitCommitLikeOperator() : 'LIKE';
|
||||
$query->orWhere($column, $operator, '%' . $term . '%');
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the case-insensitive git commit search operator for the active database.
|
||||
|
||||
@@ -11,6 +11,8 @@ final class TicketPolicy
|
||||
{
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
unset($user);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -23,7 +25,7 @@ final class TicketPolicy
|
||||
|
||||
public function create(User $user): bool
|
||||
{
|
||||
return true;
|
||||
return $user->exists;
|
||||
}
|
||||
|
||||
public function update(User $user, Ticket $ticket): bool
|
||||
|
||||
@@ -648,10 +648,9 @@ span.flatpickr-weekday {
|
||||
gap: .5rem;
|
||||
border-radius: .85rem;
|
||||
padding: .62rem 1.05rem;
|
||||
font-size: .875rem;
|
||||
font-size: .95rem;
|
||||
line-height: 1.25rem;
|
||||
font-weight: 800;
|
||||
font-size: .95rem;
|
||||
color: #ffffff !important;
|
||||
text-decoration: none !important;
|
||||
border: 1px solid rgba(255,255,255,.14);
|
||||
|
||||
@@ -53,10 +53,14 @@
|
||||
<section class="overflow-hidden rounded-2xl border border-zinc-700 bg-zinc-950 shadow-sm">
|
||||
<div class="overflow-auto">
|
||||
<table class="min-w-full border-collapse font-mono text-xs leading-6">
|
||||
<caption class="sr-only">Source code for {{ $attachmentName }}</caption>
|
||||
<thead class="sr-only">
|
||||
<tr><th scope="col">Line</th><th scope="col">Source</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($lines as $index => $line)
|
||||
<tr class="group hover:bg-zinc-900/80">
|
||||
<td class="select-none border-r border-zinc-800 bg-zinc-900 px-4 text-right text-zinc-500">{{ $index + 1 }}</td>
|
||||
<th scope="row" class="select-none border-r border-zinc-800 bg-zinc-900 px-4 text-right font-normal text-zinc-500">{{ $index + 1 }}</th>
|
||||
<td class="whitespace-pre px-4 text-zinc-100"><code>{{ $line }}</code></td>
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-zinc-200 text-sm dark:divide-zinc-700">
|
||||
<caption class="sr-only">Data table</caption>
|
||||
<thead
|
||||
class="bg-zinc-50 text-left text-xs font-semibold uppercase tracking-wide text-zinc-500 dark:bg-zinc-800 dark:text-zinc-300">
|
||||
<tr>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-zinc-200 text-sm dark:divide-zinc-700">
|
||||
<caption class="sr-only">Data table</caption>
|
||||
<thead
|
||||
class="bg-zinc-50 text-left text-xs font-semibold uppercase tracking-wide text-zinc-500 dark:bg-zinc-800 dark:text-zinc-300">
|
||||
<tr>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-zinc-200 text-sm dark:divide-zinc-700">
|
||||
<caption class="sr-only">Data table</caption>
|
||||
<thead
|
||||
class="bg-zinc-50 text-left text-xs font-semibold uppercase tracking-wide text-zinc-500 dark:bg-zinc-800 dark:text-zinc-300">
|
||||
<tr>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-zinc-200 text-sm dark:divide-zinc-700">
|
||||
<caption class="sr-only">Data table</caption>
|
||||
<thead
|
||||
class="bg-zinc-50 text-left text-xs font-semibold uppercase tracking-wide text-zinc-500 dark:bg-zinc-800 dark:text-zinc-300">
|
||||
<tr>
|
||||
|
||||
@@ -393,6 +393,7 @@
|
||||
<div
|
||||
class="overflow-hidden rounded-2xl border border-zinc-200 bg-white dark:border-zinc-700 dark:bg-zinc-900">
|
||||
<table class="min-w-full divide-y divide-zinc-200 text-sm dark:divide-zinc-700">
|
||||
<caption class="sr-only">Data table</caption>
|
||||
<thead
|
||||
class="bg-zinc-50 text-left text-xs font-semibold uppercase tracking-wide text-zinc-500 dark:bg-zinc-800 dark:text-zinc-300">
|
||||
<tr>
|
||||
@@ -543,6 +544,7 @@
|
||||
<div
|
||||
class="overflow-hidden rounded-2xl border border-zinc-200 bg-white dark:border-zinc-700 dark:bg-zinc-900">
|
||||
<table class="min-w-full divide-y divide-zinc-200 text-sm dark:divide-zinc-700">
|
||||
<caption class="sr-only">Data table</caption>
|
||||
<thead
|
||||
class="bg-zinc-50 text-left text-xs font-semibold uppercase tracking-wide text-zinc-500 dark:bg-zinc-800 dark:text-zinc-300">
|
||||
<tr>
|
||||
@@ -709,6 +711,7 @@
|
||||
<div
|
||||
class="overflow-hidden rounded-2xl border border-zinc-200 bg-white dark:border-zinc-700 dark:bg-zinc-900">
|
||||
<table class="min-w-full divide-y divide-zinc-200 text-sm dark:divide-zinc-700">
|
||||
<caption class="sr-only">Data table</caption>
|
||||
<thead class="bg-zinc-50 text-left text-xs font-semibold uppercase text-zinc-500 dark:bg-zinc-800">
|
||||
<tr>
|
||||
<th class="px-4 py-3">Policy</th>
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-zinc-200 text-sm dark:divide-zinc-700">
|
||||
<caption class="sr-only">Data table</caption>
|
||||
<thead
|
||||
class="bg-zinc-50 text-left text-xs font-semibold uppercase tracking-wide text-zinc-500 dark:bg-zinc-800 dark:text-zinc-300">
|
||||
<tr>
|
||||
|
||||
@@ -1657,7 +1657,7 @@
|
||||
|
||||
<style>
|
||||
[data-helpdesk-sidebar-cards] details > summary::-webkit-details-marker {
|
||||
|
||||
display: none;
|
||||
}
|
||||
|
||||
[data-helpdesk-sidebar-cards] details > summary {
|
||||
|
||||
@@ -45,16 +45,13 @@ final class AttachmentService
|
||||
$size = (int) Storage::disk($disk)->size($path);
|
||||
}
|
||||
|
||||
Attachment::query()->create($this->attachmentAttributes(
|
||||
ticket: $ticket,
|
||||
comment: $comment,
|
||||
userId: $userId,
|
||||
disk: $disk,
|
||||
path: $path,
|
||||
originalName: $originalName,
|
||||
mimeType: $mimeType,
|
||||
size: $size,
|
||||
));
|
||||
Attachment::query()->create($this->attachmentAttributes($ticket, $comment, $userId, [
|
||||
'disk' => $disk,
|
||||
'path' => $path,
|
||||
'original_name' => $originalName,
|
||||
'mime_type' => $mimeType,
|
||||
'size' => $size,
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,29 +69,29 @@ final class AttachmentService
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function attachmentAttributes(Ticket $ticket, ?Comment $comment, int $userId, string $disk, string $path, string $originalName, string $mimeType, int $size): array
|
||||
private function attachmentAttributes(Ticket $ticket, ?Comment $comment, int $userId, array $file): array
|
||||
{
|
||||
$attributes = [
|
||||
'ticket_id' => $ticket->id,
|
||||
'comment_id' => $comment?->id,
|
||||
'user_id' => $userId,
|
||||
'disk' => $disk,
|
||||
'path' => $path,
|
||||
'original_name' => $originalName,
|
||||
'mime_type' => $mimeType,
|
||||
'size' => $size,
|
||||
'disk' => $file['disk'],
|
||||
'path' => $file['path'],
|
||||
'original_name' => $file['original_name'],
|
||||
'mime_type' => $file['mime_type'],
|
||||
'size' => $file['size'],
|
||||
];
|
||||
|
||||
if (Schema::hasColumn('helpdesk_attachments', 'extension')) {
|
||||
$attributes['extension'] = strtolower((string) pathinfo($originalName, PATHINFO_EXTENSION));
|
||||
$attributes['extension'] = strtolower((string) pathinfo($file['original_name'], PATHINFO_EXTENSION));
|
||||
}
|
||||
|
||||
if (Schema::hasColumn('helpdesk_attachments', 'category')) {
|
||||
$attributes['category'] = $this->categoryFor($originalName, $mimeType);
|
||||
$attributes['category'] = $this->categoryFor($file['original_name'], $file['mime_type']);
|
||||
}
|
||||
|
||||
if (Schema::hasColumn('helpdesk_attachments', 'checksum_sha256') && Storage::disk($disk)->exists($path)) {
|
||||
$stream = Storage::disk($disk)->readStream($path);
|
||||
if (Schema::hasColumn('helpdesk_attachments', 'checksum_sha256') && Storage::disk($file['disk'])->exists($file['path'])) {
|
||||
$stream = Storage::disk($file['disk'])->readStream($file['path']);
|
||||
|
||||
if (is_resource($stream)) {
|
||||
$context = hash_init('sha256');
|
||||
@@ -114,23 +111,13 @@ final class AttachmentService
|
||||
{
|
||||
$extension = strtolower((string) pathinfo($originalName, PATHINFO_EXTENSION));
|
||||
|
||||
if (str_starts_with($mimeType, 'image/') || in_array($extension, ['png', 'jpg', 'jpeg', 'webp', 'gif'], true)) {
|
||||
return 'image';
|
||||
}
|
||||
|
||||
if ($extension === 'pdf' || $mimeType === 'application/pdf') {
|
||||
return 'pdf';
|
||||
}
|
||||
|
||||
if (in_array($extension, ['zip', 'tar', 'gz', '7z', 'rar'], true)) {
|
||||
return 'archive';
|
||||
}
|
||||
|
||||
if (in_array($extension, config('helpdesk.allowed_source_extensions', []), true)) {
|
||||
return 'source';
|
||||
}
|
||||
|
||||
return 'file';
|
||||
return match (true) {
|
||||
str_starts_with($mimeType, 'image/'), in_array($extension, ['png', 'jpg', 'jpeg', 'webp', 'gif'], true) => 'image',
|
||||
$extension === 'pdf', $mimeType === 'application/pdf' => 'pdf',
|
||||
in_array($extension, ['zip', 'tar', 'gz', '7z', 'rar'], true) => 'archive',
|
||||
in_array($extension, config('helpdesk.allowed_source_extensions', []), true) => 'source',
|
||||
default => 'file',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,18 +29,7 @@ final class AutomationRuleService
|
||||
return;
|
||||
}
|
||||
|
||||
$updates = array_filter([
|
||||
'priority_id' => $rule->set_priority_id,
|
||||
'category_id' => $rule->set_category_id,
|
||||
'team_id' => $rule->set_team_id,
|
||||
'project_id' => $rule->set_project_id,
|
||||
'status_id' => $rule->set_status_id,
|
||||
'agent_id' => $rule->set_agent_id,
|
||||
], static fn ($value): bool => $value !== null);
|
||||
|
||||
if ($updates !== []) {
|
||||
$ticket->forceFill($updates + ['last_activity_at' => now()])->save();
|
||||
}
|
||||
$this->applyRuleUpdates($rule, $ticket);
|
||||
});
|
||||
|
||||
return $ticket->fresh() ?? $ticket;
|
||||
@@ -48,19 +37,30 @@ final class AutomationRuleService
|
||||
|
||||
private function matches(AutomationRule $rule, Ticket $ticket, string $sender, string $mailbox): bool
|
||||
{
|
||||
if ($rule->match_sender && ! Str::contains(Str::lower($sender), Str::lower($rule->match_sender))) {
|
||||
return false;
|
||||
}
|
||||
if ($rule->match_subject && ! Str::contains(Str::lower($ticket->subject), Str::lower($rule->match_subject))) {
|
||||
return false;
|
||||
}
|
||||
if ($rule->match_mailbox && ! Str::contains(Str::lower($mailbox), Str::lower($rule->match_mailbox))) {
|
||||
return false;
|
||||
}
|
||||
if ($rule->match_category_id && (int) $ticket->category_id !== (int) $rule->match_category_id) {
|
||||
return false;
|
||||
}
|
||||
return $this->containsWhenConfigured($sender, $rule->match_sender)
|
||||
&& $this->containsWhenConfigured($ticket->subject, $rule->match_subject)
|
||||
&& $this->containsWhenConfigured($mailbox, $rule->match_mailbox)
|
||||
&& (! $rule->match_category_id || (int) $ticket->category_id === (int) $rule->match_category_id);
|
||||
}
|
||||
|
||||
return true;
|
||||
private function containsWhenConfigured(string $value, ?string $match): bool
|
||||
{
|
||||
return ! $match || Str::contains(Str::lower($value), Str::lower($match));
|
||||
}
|
||||
|
||||
private function applyRuleUpdates(AutomationRule $rule, Ticket $ticket): void
|
||||
{
|
||||
$updates = array_filter([
|
||||
'priority_id' => $rule->set_priority_id,
|
||||
'category_id' => $rule->set_category_id,
|
||||
'team_id' => $rule->set_team_id,
|
||||
'project_id' => $rule->set_project_id,
|
||||
'status_id' => $rule->set_status_id,
|
||||
'agent_id' => $rule->set_agent_id,
|
||||
], static fn ($value): bool => $value !== null);
|
||||
|
||||
if ($updates !== []) {
|
||||
$ticket->forceFill($updates + ['last_activity_at' => now()])->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ use Throwable;
|
||||
|
||||
final class GitWebhookIngestionService
|
||||
{
|
||||
private const PUSH_HOOK = 'push hook';
|
||||
|
||||
/**
|
||||
* Matches the generated Helpdesk reference format, for example HD-2026-00042.
|
||||
*/
|
||||
@@ -173,10 +175,10 @@ final class GitWebhookIngestionService
|
||||
|
||||
return match ($normalisedProvider) {
|
||||
'github' => in_array($normalisedEvent, ['push', ''], true),
|
||||
'gitlab' => in_array($normalisedEvent, ['push hook', 'push', ''], true),
|
||||
'gitea' => in_array($normalisedEvent, ['push', 'push hook', ''], true),
|
||||
'gitlab' => in_array($normalisedEvent, [self::PUSH_HOOK, 'push', ''], true),
|
||||
'gitea' => in_array($normalisedEvent, ['push', self::PUSH_HOOK, ''], true),
|
||||
'bitbucket' => in_array($normalisedEvent, ['repo push', 'push', ''], true),
|
||||
default => in_array($normalisedEvent, ['push', 'repo push', 'push hook', ''], true),
|
||||
default => in_array($normalisedEvent, ['push', 'repo push', self::PUSH_HOOK, ''], true),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -214,23 +216,14 @@ final class GitWebhookIngestionService
|
||||
{
|
||||
$commits = $payload['commits'] ?? null;
|
||||
|
||||
if (is_array($commits) && $commits !== []) {
|
||||
return array_values(array_filter($commits, static fn (mixed $commit): bool => is_array($commit)));
|
||||
if (! is_array($commits) || $commits === []) {
|
||||
$headCommit = $payload['head_commit'] ?? null;
|
||||
$commits = is_array($headCommit) ? [$headCommit] : Arr::get($payload, 'push.changes.0.commits', []);
|
||||
}
|
||||
|
||||
$headCommit = $payload['head_commit'] ?? null;
|
||||
|
||||
if (is_array($headCommit)) {
|
||||
return [$headCommit];
|
||||
}
|
||||
|
||||
$bitbucketCommits = Arr::get($payload, 'push.changes.0.commits', []);
|
||||
|
||||
if (is_array($bitbucketCommits)) {
|
||||
return array_values(array_filter($bitbucketCommits, static fn (mixed $commit): bool => is_array($commit)));
|
||||
}
|
||||
|
||||
return [];
|
||||
return is_array($commits)
|
||||
? array_values(array_filter($commits, static fn (mixed $commit): bool => is_array($commit)))
|
||||
: [];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,6 +10,7 @@ use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Str;
|
||||
use Modules\Helpdesk\Exceptions\TicketPersistenceException;
|
||||
use Modules\Helpdesk\Models\Comment;
|
||||
use Modules\Helpdesk\Models\KanbanBoard;
|
||||
use Modules\Helpdesk\Models\Status;
|
||||
@@ -45,7 +46,7 @@ final class TicketService
|
||||
}
|
||||
}
|
||||
|
||||
throw new \RuntimeException('Unable to create a unique Helpdesk ticket reference.');
|
||||
throw new TicketPersistenceException('Unable to create a unique Helpdesk ticket reference.');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,32 +57,8 @@ final class TicketService
|
||||
*/
|
||||
private function createInsideTransaction(User $user, array $data, array $files = []): Ticket
|
||||
{
|
||||
$defaultStatusSlug = (string) config('helpdesk.default_status_slug', 'new');
|
||||
$status = Schema::hasTable('helpdesk_statuses') && Schema::hasColumn('helpdesk_statuses', 'is_default')
|
||||
? Status::query()->where('is_default', true)->orderBy('sort_order')->first()
|
||||
: null;
|
||||
|
||||
if (! $status) {
|
||||
$status = Status::query()->where('slug', $defaultStatusSlug)->first();
|
||||
}
|
||||
|
||||
if (! $status) {
|
||||
$status = Status::query()->create([
|
||||
'name' => 'New',
|
||||
'slug' => $defaultStatusSlug,
|
||||
'color' => 'sky',
|
||||
'sort_order' => 1,
|
||||
'is_closed' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
$boardId = $data['board_id'] ?? null;
|
||||
if (blank($boardId) && Schema::hasTable('helpdesk_kanban_boards')) {
|
||||
$boardId = KanbanBoard::query()
|
||||
->where('is_default', true)
|
||||
->orderBy('sort_order')
|
||||
->value('id') ?: KanbanBoard::query()->orderBy('sort_order')->value('id');
|
||||
}
|
||||
$status = $this->resolveInitialStatus();
|
||||
$boardId = $this->resolveBoardId($data['board_id'] ?? null);
|
||||
|
||||
/** @var Ticket $ticket */
|
||||
$ticket = Ticket::query()->create([
|
||||
@@ -102,9 +79,7 @@ final class TicketService
|
||||
'last_activity_at' => now(),
|
||||
]);
|
||||
|
||||
if (! empty($data['tag_ids']) && is_array($data['tag_ids'])) {
|
||||
$ticket->tags()->sync(array_values(array_unique(array_map('intval', $data['tag_ids']))));
|
||||
}
|
||||
$this->syncTags($ticket, $data['tag_ids'] ?? null);
|
||||
|
||||
$ticket = $this->automation->apply($ticket, $data);
|
||||
$ticket = $this->sla->applyPolicy($ticket);
|
||||
@@ -117,6 +92,43 @@ final class TicketService
|
||||
return $ticket;
|
||||
}
|
||||
|
||||
private function resolveInitialStatus(): Status
|
||||
{
|
||||
$defaultStatusSlug = (string) config('helpdesk.default_status_slug', 'new');
|
||||
$status = Schema::hasTable('helpdesk_statuses') && Schema::hasColumn('helpdesk_statuses', 'is_default')
|
||||
? Status::query()->where('is_default', true)->orderBy('sort_order')->first()
|
||||
: null;
|
||||
|
||||
$status ??= Status::query()->where('slug', $defaultStatusSlug)->first();
|
||||
|
||||
return $status ?? Status::query()->create([
|
||||
'name' => 'New',
|
||||
'slug' => $defaultStatusSlug,
|
||||
'color' => 'sky',
|
||||
'sort_order' => 1,
|
||||
'is_closed' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
private function resolveBoardId(mixed $boardId): mixed
|
||||
{
|
||||
if (! blank($boardId) || ! Schema::hasTable('helpdesk_kanban_boards')) {
|
||||
return $boardId;
|
||||
}
|
||||
|
||||
return KanbanBoard::query()->where('is_default', true)->orderBy('sort_order')->value('id')
|
||||
?: KanbanBoard::query()->orderBy('sort_order')->value('id');
|
||||
}
|
||||
|
||||
private function syncTags(Ticket $ticket, mixed $tagIds): void
|
||||
{
|
||||
if (! is_array($tagIds) || $tagIds === []) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ticket->tags()->sync(array_values(array_unique(array_map('intval', $tagIds))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether a database error was caused by the ticket reference unique index.
|
||||
*/
|
||||
@@ -137,52 +149,69 @@ final class TicketService
|
||||
public function comment(Ticket $ticket, User $user, string $body, bool $internal = false, array $files = [], ?int $parentId = null, ?string $subject = null): Comment
|
||||
{
|
||||
return DB::transaction(function () use ($ticket, $user, $body, $internal, $files, $parentId, $subject): Comment {
|
||||
$parent = $parentId === null
|
||||
? null
|
||||
: Comment::query()
|
||||
->where('ticket_id', $ticket->id)
|
||||
->findOrFail($parentId);
|
||||
|
||||
$guid = (string) Str::uuid();
|
||||
$unid = strtoupper(hash('sha256', $guid . '|' . $ticket->id . '|' . microtime(true)));
|
||||
$parentUnid = $parent?->unid;
|
||||
$rootUnid = $parent?->root_unid ?: $parentUnid ?: $unid;
|
||||
$plainTextBody = trim(preg_replace('/\s+/', ' ', strip_tags($body)) ?: '');
|
||||
|
||||
$payload = [
|
||||
'parent_id' => $parentId,
|
||||
'user_id' => $user->id,
|
||||
'body' => $body,
|
||||
'body_text' => $plainTextBody,
|
||||
'is_internal' => $internal,
|
||||
'guid' => $guid,
|
||||
'unid' => $unid,
|
||||
'parent_unid' => $parentUnid,
|
||||
'root_unid' => $rootUnid,
|
||||
'originator_id' => $unid . ':1',
|
||||
'sync_sequence' => 1,
|
||||
'sync_hash' => hash('sha256', $body),
|
||||
'source_system' => 'wms-helpdesk',
|
||||
];
|
||||
|
||||
if (Schema::hasColumn('helpdesk_comments', 'subject')) {
|
||||
$payload['subject'] = trim((string) ($subject ?: ($parentId === null ? 'Response' : 'RE: Response')));
|
||||
}
|
||||
$parent = $this->resolveParentComment($ticket, $parentId);
|
||||
$payload = $this->commentPayload($ticket, $user, $body, $internal, $parent, $parentId, $subject);
|
||||
|
||||
/** @var Comment $comment */
|
||||
$comment = $ticket->comments()->create($payload);
|
||||
|
||||
$ticket->forceFill(['last_activity_at' => now()])->save();
|
||||
if (! $internal) {
|
||||
$this->sla->recordPublicResponse($ticket, $user);
|
||||
}
|
||||
$this->attachments->storeMany($ticket, $files, (int) $user->id, $comment);
|
||||
$this->workflow->dispatch($ticket->fresh(['status', 'priority', 'category', 'project', 'team']) ?? $ticket, $parentId === null ? 'ticket.commented' : 'ticket.reply_created', $user);
|
||||
$this->afterCommentCreated($ticket, $user, $comment, $files, $internal, $parentId);
|
||||
|
||||
return $comment->fresh(['user', 'attachments']) ?? $comment;
|
||||
});
|
||||
}
|
||||
|
||||
private function resolveParentComment(Ticket $ticket, ?int $parentId): ?Comment
|
||||
{
|
||||
return $parentId === null
|
||||
? null
|
||||
: Comment::query()->where('ticket_id', $ticket->id)->findOrFail($parentId);
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
private function commentPayload(Ticket $ticket, User $user, string $body, bool $internal, ?Comment $parent, ?int $parentId, ?string $subject): array
|
||||
{
|
||||
$guid = (string) Str::uuid();
|
||||
$unid = strtoupper(hash('sha256', $guid . '|' . $ticket->id . '|' . microtime(true)));
|
||||
$parentUnid = $parent?->unid;
|
||||
$payload = [
|
||||
'parent_id' => $parentId,
|
||||
'user_id' => $user->id,
|
||||
'body' => $body,
|
||||
'body_text' => trim(preg_replace('/\s+/', ' ', strip_tags($body)) ?: ''),
|
||||
'is_internal' => $internal,
|
||||
'guid' => $guid,
|
||||
'unid' => $unid,
|
||||
'parent_unid' => $parentUnid,
|
||||
'root_unid' => $parent?->root_unid ?: $parentUnid ?: $unid,
|
||||
'originator_id' => $unid . ':1',
|
||||
'sync_sequence' => 1,
|
||||
'sync_hash' => hash('sha256', $body),
|
||||
'source_system' => 'wms-helpdesk',
|
||||
];
|
||||
|
||||
if (Schema::hasColumn('helpdesk_comments', 'subject')) {
|
||||
$defaultSubject = $parentId === null ? 'Response' : 'RE: Response';
|
||||
$payload['subject'] = trim((string) ($subject ?: $defaultSubject));
|
||||
}
|
||||
|
||||
return $payload;
|
||||
}
|
||||
|
||||
/** @param array<int, UploadedFile> $files */
|
||||
private function afterCommentCreated(Ticket $ticket, User $user, Comment $comment, array $files, bool $internal, ?int $parentId): void
|
||||
{
|
||||
$ticket->forceFill(['last_activity_at' => now()])->save();
|
||||
|
||||
if (! $internal) {
|
||||
$this->sla->recordPublicResponse($ticket, $user);
|
||||
}
|
||||
|
||||
$this->attachments->storeMany($ticket, $files, (int) $user->id, $comment);
|
||||
$event = $parentId === null ? 'ticket.commented' : 'ticket.reply_created';
|
||||
$freshTicket = $ticket->fresh(['status', 'priority', 'category', 'project', 'team']) ?? $ticket;
|
||||
$this->workflow->dispatch($freshTicket, $event, $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a ticket.
|
||||
*/
|
||||
|
||||
@@ -34,7 +34,7 @@ final class WorkflowNotificationService
|
||||
$recipient = $this->recipient($template->to_role, $ticket, $actor);
|
||||
|
||||
if ($recipient === null || blank($recipient->email ?? null)) {
|
||||
$this->log($template, $ticket, $event, null, 'skipped', 'No recipient email was available.');
|
||||
$this->log($template, $ticket, $event, ['recipient' => null, 'status' => 'skipped', 'error' => 'No recipient email was available.']);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -42,7 +42,6 @@ final class WorkflowNotificationService
|
||||
$trackingToken = Str::random(48);
|
||||
$subject = $this->renderText($template->subject, $ticket, $actor);
|
||||
$html = $this->wrapHtml($this->renderText($template->html_body, $ticket, $actor), $ticket, $trackingToken);
|
||||
$text = $this->renderText($template->text_body ?: strip_tags($template->html_body), $ticket, $actor);
|
||||
|
||||
try {
|
||||
Mail::html($html, function ($message) use ($recipient, $template, $subject): void {
|
||||
@@ -57,10 +56,10 @@ final class WorkflowNotificationService
|
||||
}
|
||||
});
|
||||
|
||||
$this->log($template, $ticket, $event, (string) $recipient->email, 'sent', null, $subject, $trackingToken);
|
||||
$this->log($template, $ticket, $event, ['recipient' => (string) $recipient->email, 'status' => 'sent', 'subject' => $subject, 'tracking_token' => $trackingToken]);
|
||||
} catch (Throwable $exception) {
|
||||
Log::warning('Helpdesk workflow email failed.', ['event' => $event, 'ticket_id' => $ticket->id, 'error' => $exception->getMessage()]);
|
||||
$this->log($template, $ticket, $event, (string) $recipient->email, 'failed', $exception->getMessage(), $subject);
|
||||
$this->log($template, $ticket, $event, ['recipient' => (string) $recipient->email, 'status' => 'failed', 'error' => $exception->getMessage(), 'subject' => $subject]);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -158,17 +157,18 @@ final class WorkflowNotificationService
|
||||
return '<img src="' . e($url) . '" width="1" height="1" alt="" style="display:none" />';
|
||||
}
|
||||
|
||||
private function log(WorkflowTemplate $template, Ticket $ticket, string $event, ?string $recipient, string $status, ?string $error = null, ?string $subject = null, ?string $trackingToken = null): void
|
||||
/** @param array{recipient:?string,status:string,error?:?string,subject?:?string,tracking_token?:?string} $details */
|
||||
private function log(WorkflowTemplate $template, Ticket $ticket, string $event, array $details): void
|
||||
{
|
||||
WorkflowLog::query()->create([
|
||||
'template_id' => $template->id,
|
||||
'ticket_id' => $ticket->id,
|
||||
'event' => $event,
|
||||
'recipient' => $recipient,
|
||||
'subject' => $subject,
|
||||
'status' => $status,
|
||||
'tracking_token' => $trackingToken,
|
||||
'error' => $error,
|
||||
'recipient' => $details['recipient'],
|
||||
'subject' => $details['subject'] ?? null,
|
||||
'status' => $details['status'],
|
||||
'tracking_token' => $details['tracking_token'] ?? null,
|
||||
'error' => $details['error'] ?? null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,14 +22,12 @@ trait BuildsHelpdeskFixtures
|
||||
{
|
||||
protected function user(array $attributes = []): User
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = User::factory()->create(array_merge([
|
||||
/** @var User */
|
||||
return User::factory()->create(array_merge([
|
||||
'name' => 'Helpdesk User',
|
||||
'email' => fake()->unique()->safeEmail(),
|
||||
'password' => Hash::make('password'),
|
||||
], $attributes));
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
protected function agent(array $attributes = []): User
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<caption class="sr-only">Data table</caption>
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Part Number</th>
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
// M3 now uses Core's PostgreSQL connection. No per-user DB credentials are required.
|
||||
|
||||
|
||||
return [
|
||||
|
||||
#'nonWorkingHourCode' => ['73,85,89,90,91,92,86,99'],
|
||||
'autorefresh_all' => ['00:15'],
|
||||
'autorefresh_notall' => ['00:15'],
|
||||
|
||||
'payrollCodes' => ['33,49,75,94,98,102,171'],
|
||||
|
||||
'min_work_hours_for_break' => ['4'],
|
||||
|
||||
'ignore_picks_that_last_longer_than_this_many_hours' => ['8'],
|
||||
|
||||
'env_ports' => ['test'=>'10004','live'=>'10005'],
|
||||
|
||||
'hold_code_array' => ['A'=>'Admin Hold',
|
||||
'C'=>'AR Past Due',
|
||||
'D'=>'Over Credit Limit',
|
||||
'E'=>'Over Order Limit',
|
||||
'F'=>'Address Check Fail',
|
||||
'Q'=>'Quote Hold',
|
||||
'H'=>'A/R Cust Hold',
|
||||
'I'=>'EDI Hold',
|
||||
'P'=>'EDI Price Hold',
|
||||
'Z'=>'Haz Hold',
|
||||
'X'=>'CID Hold',
|
||||
'W'=>'Web Hold',
|
||||
'T'=>'Duplicate Hold'],
|
||||
|
||||
'user_array' => '', //$user_array,
|
||||
'misc' => [
|
||||
'discountCarrierRateForCustomerPriceLTL'=>0.00, # This is the percent off list that we want to charge customers
|
||||
'discountCarrierRateForCustomerPriceParcel'=>0.00, # This is the percent off list that we want to charge customers - to use in ship confirm
|
||||
],
|
||||
'transxTypes' =>[
|
||||
'ICM710E' => 'Splitting delivery orders',
|
||||
'ICM710E13' => 'Pre-Splitting interco delivery orders',
|
||||
'ICM710E12' => 'Pre-Splitting customer delivery orders',
|
||||
'M3InventoryReportListURL' => 'Retrieve inventory on hand',
|
||||
'M3InventoryReportReplen' => 'Retrieve Replenishments',
|
||||
'M3ReceiverAPI' => 'Post Splitting delivery orders',
|
||||
'PdfStorageAPI' => 'PDF document storage',
|
||||
'PackSyst4tray' => 'Change of qty picked after picking',
|
||||
'CloseShipmentCoChargeAPI' => 'Closing delivery orders',
|
||||
'TransferAPIURL' => 'Move goods to Pack/Dock locations',
|
||||
'OP705API' => 'Closing a manifest',
|
||||
'CloseShipmentCoChargeAPIMfest' => 'Batch closing for M3 manifests at night',
|
||||
'M3-General' => 'General - contact MPBA',
|
||||
'UpdateShipmentNumber' => 'Update Shipment Number',
|
||||
],
|
||||
'curlTimeOut' => 30,
|
||||
'PHPTimeOut' => 600,
|
||||
'PHPTimeOutCL'=> 1000,
|
||||
'maxRecDL' => 20000,
|
||||
'maxRecCL' => 55000,
|
||||
'BadChars' => ['–','\t','\n','\u20134807','\u20131','\u201333','\u2013671' ,'Ÿ','á', 'é', 'í', 'ó' ,'ú','“','”'],
|
||||
'PdfPath' => env('M3_LABELS_PATH', storage_path('app/m3/labels') . DIRECTORY_SEPARATOR), # Warning : The path for PDF storage is shared by all Instances and should not be altered
|
||||
'DUMMYPDF' => '',
|
||||
'uom_size' => ['110-142-303'=>'mm',
|
||||
'110-143-321'=>'mm',
|
||||
'110-143-322'=>'in'], # unit of mesure for boxes lengths mm or in
|
||||
'uom_wt' => ['110-142-303'=>'kg',
|
||||
'110-143-321'=>'kg',
|
||||
'110-143-322'=>'lbs'], # unit of mesure for boxes weight kg or lbs
|
||||
|
||||
#STATUS ARRAY FOR ICM688M1
|
||||
'status_ICM688M1_array' => [
|
||||
"P"=>"Pending error checking by splitting (OP510E2)",
|
||||
"H"=>"Hold as error found (OP510E3)",
|
||||
"L"=>"Ready to pick",
|
||||
"I"=>"In picking",
|
||||
"F"=>"In packing",
|
||||
"X"=>"Cancelled",
|
||||
"C"=>"Packed",
|
||||
"B"=>"Loaded",
|
||||
"a"=>"Manually removed from Sentinel ship confirm screen",
|
||||
"A"=>"ShipConfirmed" ],
|
||||
|
||||
'whsePerf_targets' => [
|
||||
'all_notes'=>'90', 'all_dollars'=>'85', 'all_weight'=>'90',
|
||||
'ltl_notes'=>'90', 'ltl_dollars'=>'95', 'ltl_weight'=>'99',
|
||||
'parcel_notes'=>'90', 'parcel_dollars'=>'75', 'parcel_weight'=>'80'
|
||||
],
|
||||
'2Ship' => [
|
||||
# 2Ship WS_Key
|
||||
# live $TwoShip_Key="FED945D1-5DC7-415E-BDAB-16347E7C1304";
|
||||
# test $TwoShip_Key="45027F2A-EDA6-4C16-8AD4-9BC70CE94AB8";
|
||||
'TwoShip_Key' => "45027F2A-EDA6-4C16-8AD4-9BC70CE94AB8",
|
||||
'end_point' =>"https://euroapi.2ship.com/api/",
|
||||
'hold_update' =>"UpdateOnHoldOrder_V1",
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
# PayRollCodes are the keys (left) to read LBPF, lines per hours (right)
|
||||
return [
|
||||
|
||||
'lph_per_code_array' => ['16'=>'30',
|
||||
'33'=>'12',
|
||||
'49'=>'25',
|
||||
'66'=>'60',
|
||||
'75'=>'15',
|
||||
'94'=>'40',
|
||||
'98'=>'8',
|
||||
'102'=>'10',
|
||||
'171'=>'17'
|
||||
]
|
||||
|
||||
|
||||
];
|
||||
# '75'=>'26',
|
||||
# '75'=>'23',
|
||||
# '33'=>'13', #2025-08-04
|
||||
|
||||
# Found in BLDPERFST rpg pgm in EWRPGSRC / EWSRCTST
|
||||
# PICKING stats
|
||||
# when a5sentview in ('7','9') then 33
|
||||
# when a5sentview = 5 then 49
|
||||
# when a5sentview = 12 then 98
|
||||
# when a5sentview in ('2','10') then 75
|
||||
# when a5sentview in ('1','3','4','11') then 94
|
||||
# when a5sentview = 8 then 102
|
||||
# when a5sentview = 6 then 171
|
||||
# else 999
|
||||
|
||||
# PACKING stats
|
||||
# case when (select AYTYPE from ICM695M1
|
||||
# where AYINTBOX=AZINTBOX
|
||||
# and AYSENTPKR=AZSENTPKR FETCH FIRST ROW ONLY)
|
||||
# in ('','BX') then '16' else '66' end as AYTYPE,
|
||||
|
||||
?>
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
return [
|
||||
'name' => 'M3',
|
||||
'features' =>
|
||||
[
|
||||
],
|
||||
'connection' => env('M3_DB_CONNECTION', env('DB_CONNECTION', 'pgsql')),
|
||||
'labels_path' => env('M3_LABELS_PATH', storage_path('app/m3/labels')),
|
||||
'closing_orders_path' => env('M3_CLOSING_ORDERS_PATH', storage_path('app/m3/closing-orders')),
|
||||
];
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use DB;
|
||||
use Config;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Log;
|
||||
use Str;
|
||||
|
||||
use Modules\M3\Http\Controllers\API\CloseShipment;
|
||||
|
||||
class CallCloseAPI extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'command:CallCloseAPI {user?} {manifest?} {co?} {whs?} ';
|
||||
|
||||
protected $description = 'Call Close API';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
//$this->info('Start CallCloseAPI...');
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('max_input_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOut'));
|
||||
|
||||
try {
|
||||
# Get the Calling User
|
||||
$userId = $this->argument('user');
|
||||
$SHUSER = isset($userId) ? $userId : (m3_user() !== '' ? Str::upper(trim(m3_user())) : '');
|
||||
|
||||
# Get the Manifest Number
|
||||
$manifest = $this->argument('manifest');
|
||||
$MANIFESTNum = isset($manifest) ? $manifest : '';
|
||||
$co = $this->argument('co');
|
||||
$APCO = isset($co) ? $co : '';
|
||||
$whs = $this->argument('whs');
|
||||
$APWHS = isset($whs) ? $whs : '';
|
||||
|
||||
// if ($SHUSER!='') {
|
||||
// Log::channel('dailyCron')->info("Cron...Start CallCloseAPI...For Manifest#: ".$MANIFESTNum); // ".$SHUSER."
|
||||
|
||||
if( $MANIFESTNum==''){
|
||||
# Get Macpickers from ICM705M1
|
||||
$ICM705M1 = DB::connection(config('m3.connection', 'pgsql'))->table('icm705m1')
|
||||
->select('APMANIFEST','APCO','APWHS')
|
||||
->where('APSPARE2','')
|
||||
->where('APMANIFEST','!=','0')
|
||||
->whereRaw('EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - APLDCLOZ)) / 60 > 15')
|
||||
->orderBy('APMANIFEST','desc')
|
||||
->get();
|
||||
// dump($ICM705M1);
|
||||
|
||||
if (count($ICM705M1)>0) {
|
||||
# Loop the Results from $ICM705M1
|
||||
foreach ($ICM705M1 as $key => $ICM705M1R) {
|
||||
$MANIFESTNum = $ICM705M1R->APMANIFEST;
|
||||
|
||||
$USERCO = isset($ICM705M1R->APCO) ? $ICM705M1R->APCO : '';
|
||||
$USERWH = isset($ICM705M1R->APWHS) ? $ICM705M1R->APWHS : '';
|
||||
|
||||
# Update ICM705M1 and set APSPARE2 to P
|
||||
$ICM705M1U = DB::connection(config('m3.connection', 'pgsql'))->table('icm705m1')
|
||||
->where('APMANIFEST',$MANIFESTNum)
|
||||
->where('APCO',$USERCO)
|
||||
->where('APWHS',$USERWH)
|
||||
->update(["APSPARE2"=>"P"]);
|
||||
|
||||
$myRequest = new Request();
|
||||
$myRequest->setMethod('POST');
|
||||
$myRequest->request->add([
|
||||
'WHS' => $USERWH,
|
||||
'COMPANY' => $USERCO,
|
||||
'TRANSTYPE' => 'M',
|
||||
'MANIFEST' => $MANIFESTNum
|
||||
]);
|
||||
$callCloseShipment = CloseShipment::CloseShipmentCoChargeAPI($myRequest);
|
||||
$responseData = $callCloseShipment->getData();
|
||||
$jsonData = json_encode($responseData);
|
||||
Log::channel('dailyCron')->info("Close Shipment API Response for Manifest:".(string)(int)$MANIFESTNum.'-'.$jsonData);
|
||||
}
|
||||
}
|
||||
}
|
||||
# Call Closing for a specific Manifest
|
||||
else{
|
||||
# Get Macpickers from ICM705M1
|
||||
$ICM705M1 = DB::connection(config('m3.connection', 'pgsql'))->table('icm705m1')
|
||||
->select('APMANIFEST','APCO','APWHS')
|
||||
->where('APSPARE2','')
|
||||
->where('APCO',$APCO)
|
||||
->where('APWHS',$APWHS)
|
||||
->where('APMANIFEST','=',$MANIFESTNum)
|
||||
->first();
|
||||
|
||||
# Update ICM705M1 and set APSPARE2 to P
|
||||
$ICM705M1U = DB::connection(config('m3.connection', 'pgsql'))->table('icm705m1')
|
||||
->where('APMANIFEST',$MANIFESTNum)
|
||||
->where('APCO',$APCO)
|
||||
->where('APWHS',$APWHS)
|
||||
->update(["APSPARE2"=>"P"]);
|
||||
|
||||
$myRequest = new Request();
|
||||
$myRequest->setMethod('POST');
|
||||
|
||||
$myRequest->request->add([
|
||||
'WHS' => $APWHS ,
|
||||
'COMPANY' => $APCO,
|
||||
'TRANSTYPE' => 'M',
|
||||
'MANIFEST' => $MANIFESTNum
|
||||
]);
|
||||
|
||||
$callCloseShipment = CloseShipment::CloseShipmentCoChargeAPI($myRequest);
|
||||
$responseData = $callCloseShipment->getData();
|
||||
$jsonData = json_encode($responseData);
|
||||
Log::channel('dailyCron')->info("Close Shipment API Response for Manifest:".$MANIFESTNum.'-'.$jsonData);
|
||||
return 1;
|
||||
}
|
||||
// }
|
||||
// else{
|
||||
// Log::channel('dailyCron')->error('A user must be defined...');
|
||||
|
||||
// $this->error('A user must be defined...');
|
||||
// }
|
||||
|
||||
}
|
||||
catch (\Throwable $th) {
|
||||
// Log::error($th);
|
||||
Log::channel('dailyCron')->error($th);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use DB;
|
||||
use Config;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Log;
|
||||
use Str;
|
||||
|
||||
use Excel;
|
||||
use Storage;
|
||||
|
||||
class ClosedOrderSaveXls extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'command:ClosedOrderSaveXls {user?} {co?} {whs?} {pl?}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Save Orders Closed Lines to Excel';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
//$this->info('Start CallCloseAPI...');
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOutCL'));
|
||||
ini_set('max_input_time', Config::get('arrays.PHPTimeOutCL'));
|
||||
ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOutCL'));
|
||||
ini_set('memory_limit', '1024M');
|
||||
|
||||
try {
|
||||
Log::channel('dailyCron')->info("Cron...Start Save Orders Closed Lines to Excel");
|
||||
|
||||
# Get the Calling User
|
||||
$userId = $this->argument('user');
|
||||
$SHUSER = isset($userId) ? $userId : (m3_user() !== '' ? Str::upper(trim(m3_user())) : '');
|
||||
|
||||
$CO = $this->argument('co');
|
||||
$COMPANY = isset($CO) ? trim($CO) : '';
|
||||
$PWHS = $this->argument('whs');
|
||||
$WHS = isset($PWHS) ? trim($PWHS) : '';
|
||||
$PPL = $this->argument('pl');
|
||||
$PLANT = isset($PPL) ? trim($PPL) : '';
|
||||
|
||||
# Generate last Month Report
|
||||
$date = new \DateTime('FIRST DAY OF THIS MONTH');
|
||||
$date->modify('-1 month');
|
||||
$fromPreviousMonth = $date->format('Y-m-d');
|
||||
$toPreviousMonth = $date->modify('last day of this month')->format('Y-m-d');
|
||||
$reportDate = \DateTime::createFromFormat('Y-m-d', $fromPreviousMonth )->format('Ymd');
|
||||
$toreportDate = \DateTime::createFromFormat('Y-m-d', $toPreviousMonth )->format('Ymd');
|
||||
$reportDateWD = $fromPreviousMonth;
|
||||
$toreportDateWD = $toPreviousMonth;
|
||||
|
||||
if ($WHS == '321') {
|
||||
$prevMonthFile = 'Closedorderlinesreport_'.$reportDateWD.'-'.$toreportDateWD.'.xlsx';
|
||||
}
|
||||
else {
|
||||
$prevMonthFile = $WHS.'/Closedorderlinesreport_'.$reportDateWD.'-'.$toreportDateWD.'-'.$WHS.'.xlsx';
|
||||
}
|
||||
|
||||
$this->info("Generate Last Month Report...");
|
||||
$this->info("From Date: ".$reportDate);
|
||||
$this->info("To Date: ".$toreportDate);
|
||||
|
||||
# Check that the Excel file Exist
|
||||
$prevMonthFileExist = Storage::disk('publicCL')->exists($prevMonthFile) ? false: true ;
|
||||
$this->info("Prev Month File Exist: " .$prevMonthFileExist);
|
||||
|
||||
if($reportDate!='' && $COMPANY!='' && $WHS!='' && $PLANT!='' && $prevMonthFileExist ){
|
||||
# Case 729: Add Currency code A1SHCURR FROM ICM666M
|
||||
$ICM688M2 = DB::connection(config('m3.connection', 'pgsql'))
|
||||
->select("
|
||||
SELECT (SHDT || ' ' || SHTIME) AS DATECLOSED, A5MACPKR, A5ONO,
|
||||
A4OFSTRM,
|
||||
A5PMPWHT*A5PACKED AS WEIGHT,
|
||||
A4SCAC,
|
||||
A4SHIPTYPE,
|
||||
(SELECT A4REFORD FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) AS A4REFORD,
|
||||
A5PART, A5RSVQTY, A5PACKED, A5RSVQTY - A5PACKED AS CALCULATED_COLUMN,
|
||||
A5SLUNPR * A5PACKED AS ANOTHER_CALCULATED_COLUMN,
|
||||
(SELECT A4SHSHNM FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) AS A4SHSHNM ,
|
||||
CASE WHEN SHDT IS NULL THEN (SELECT SHDATA FROM ICM699M WHERE SHMACPKR=A5MACPKR AND SHTYPE='M3-Res-out' AND SHSOURCE='CloseShipmentCoChargeAPI' ORDER BY SHDT DESC, SHTIME DESC FETCH FIRST 1 ROWS ONLY) ELSE '' END AS REASON,
|
||||
A1SHCURR,
|
||||
CASE
|
||||
WHEN (SELECT A4SHIPTYPE FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) = 'LTL'
|
||||
THEN (SELECT A4RATETCP FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) * ".(100.00 - Config::get('arrays.misc.discountCarrierRateForCustomerPriceLTL'))/100 ."
|
||||
ELSE (SELECT A4RATETCP FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) * ".(100.00 - Config::get('arrays.misc.discountCarrierRateForCustomerPriceParcel') )/100 ."
|
||||
END AS FREIGHT
|
||||
FROM ICM688M2
|
||||
LEFT JOIN ICM699M ON SHMACPKR=A5MACPKR AND SHTYPE='M3-Res-out' AND SHDATA LIKE 'Success%' AND SHSOURCE='CloseShipmentCoChargeAPI'
|
||||
LEFT JOIN ICM666M ON A1DELNO=A5MACPKR AND A1ONO=A5ONO AND A1PKLN=A5BRADLN
|
||||
LEFT JOIN ICM688M1 ON A4MACPKR=A5MACPKR
|
||||
WHERE A5MACPKR IN (
|
||||
SELECT DISTINCT AYMACPKR
|
||||
FROM ICM695M1
|
||||
WHERE AYSTATUS IN ('Z','z') AND AYAPR8N002 BETWEEN $reportDate AND $toreportDate
|
||||
)
|
||||
AND A5CO=$COMPANY AND A5WHS=$WHS AND A5PLANT=$PLANT
|
||||
");
|
||||
|
||||
// $newItem = ["A5MACPKR" => 'Delivery #', "A5ONO" => 'Order #', "A4REFORD" => 'Order Type',"A5PART" => 'Part #',"A5RSVQTY" => 'Reserved',
|
||||
// "A5PACKED" => 'Packed',"CALCULATED_COLUMN" => 'Back Order Qty',"ANOTHER_CALCULATED_COLUMN" => 'Value Packed $',"A4SHSHNM" => 'Customer name',
|
||||
// "SHDT" => 'Date',"SHTIME" => 'Time',"REASON" => 'Failure Reason','A1SHCURR'=> 'Currency Code','FREIGHT'=> 'Freight'];
|
||||
|
||||
$newItem = ["DATECLOSED" => 'Close Date',"A5MACPKR" => 'Delivery #', "A5ONO" => 'Order #',
|
||||
"A4OFSTRM" => 'Terms',"WEIGHT" => 'Weight',"A4SCAC" => 'Carrier',"A4SHIPTYPE" => 'Mode (Parcel, Air, TL or LTL)',
|
||||
"A4REFORD" => 'Order Type',"A5PART" => 'Part #',"A5RSVQTY" => 'Reserved',
|
||||
"A5PACKED" => 'Packed',"CALCULATED_COLUMN" => 'Back Order Qty',"ANOTHER_CALCULATED_COLUMN" => 'Value Packed $',"A4SHSHNM" => 'Customer name',
|
||||
"REASON" => 'Failure Reason','A1SHCURR'=> 'Currency Code','FREIGHT'=> 'Freight'];
|
||||
|
||||
$ICM688M2Col = collect($ICM688M2);
|
||||
$ICM688M2Col->prepend($newItem);
|
||||
|
||||
# Count records before exporting to excel : Max 55K records are allowed
|
||||
$ICM688M2Count = $ICM688M2Col->count();
|
||||
# Set Max allowed records
|
||||
$maxRecords = Config::get('arrays.maxRecCL');
|
||||
if ($ICM688M2Count>$maxRecords) {
|
||||
Log::channel('dailyCron')->info('Maximum allowed records for Excel export is: '.number_format($maxRecords).' current records: '.number_format($ICM688M2Count));
|
||||
}
|
||||
}
|
||||
else{
|
||||
$ICM688M2Col = collect();
|
||||
}
|
||||
|
||||
if ($ICM688M2Col->count()>0) {
|
||||
$this->info("Saving Last Month Excel Report to Disk");
|
||||
Log::channel('dailyCron')->info("Saving Last Month Excel Report to Disk");
|
||||
|
||||
# Store the File to Storage
|
||||
app(\Modules\M3\Services\SpreadsheetExport::class)->store($ICM688M2Col, $prevMonthFile, 'publicCL');
|
||||
# Other File Formats : \Maatwebsite\Excel\Excel::CSV , ,\Maatwebsite\Excel\Excel::ODS
|
||||
}
|
||||
else{
|
||||
Log::channel('dailyCron')->info("Monthly report, no records found: Nothing to save...");
|
||||
}
|
||||
|
||||
# Generate current Month Report
|
||||
$now = new \DateTime();
|
||||
$first_day_of_month = $now->format('Y-m-01');
|
||||
$current_date = $now->format('Y-m-d');
|
||||
$reportDate2 = \DateTime::createFromFormat('Y-m-d', $first_day_of_month )->format('Ymd');
|
||||
$toreportDate2 = \DateTime::createFromFormat('Y-m-d', $current_date )->format('Ymd');
|
||||
|
||||
if ($WHS == '321') {
|
||||
$currentMonthFile = 'first_of_month_to_current_date.xlsx';
|
||||
}
|
||||
else{
|
||||
$currentMonthFile = $WHS.'/first_of_month_to_current_date_'.$WHS.'.xlsx';
|
||||
}
|
||||
|
||||
$this->info("Generate Current Month Report...");
|
||||
$this->info("From Date: ".$reportDate2);
|
||||
$this->info("To Date : ".$toreportDate2);
|
||||
|
||||
if($reportDate2!='' && $COMPANY!='' && $WHS!='' && $PLANT!=''){
|
||||
$this->info(">>> Proceed...");
|
||||
|
||||
# Case 729: Add Currency code A1SHCURR FROM ICM666M
|
||||
$ICM688M2 = DB::connection(config('m3.connection', 'pgsql'))
|
||||
->select("
|
||||
SELECT (SHDT || ' ' || SHTIME) AS DATECLOSED, A5MACPKR, A5ONO,
|
||||
A4OFSTRM,
|
||||
A5PMPWHT*A5PACKED AS WEIGHT,
|
||||
A4SCAC,
|
||||
A4SHIPTYPE,
|
||||
(SELECT A4REFORD FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) AS A4REFORD,
|
||||
A5PART, A5RSVQTY, A5PACKED, A5RSVQTY - A5PACKED AS CALCULATED_COLUMN,
|
||||
A5SLUNPR * A5PACKED AS ANOTHER_CALCULATED_COLUMN,
|
||||
(SELECT A4SHSHNM FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) AS A4SHSHNM ,
|
||||
CASE WHEN SHDT IS NULL THEN (SELECT SHDATA FROM ICM699M WHERE SHMACPKR=A5MACPKR AND SHTYPE='M3-Res-out' AND SHSOURCE='CloseShipmentCoChargeAPI' ORDER BY SHDT DESC, SHTIME DESC FETCH FIRST 1 ROWS ONLY) ELSE '' END AS REASON,
|
||||
A1SHCURR,
|
||||
CASE
|
||||
WHEN (SELECT A4SHIPTYPE FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) = 'LTL'
|
||||
THEN (SELECT A4RATETCP FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) * ".(100.00 - Config::get('arrays.misc.discountCarrierRateForCustomerPriceLTL'))/100 ."
|
||||
ELSE (SELECT A4RATETCP FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) * ".(100.00 - Config::get('arrays.misc.discountCarrierRateForCustomerPriceParcel') )/100 ."
|
||||
END AS FREIGHT
|
||||
FROM ICM688M2
|
||||
LEFT JOIN ICM699M ON SHMACPKR=A5MACPKR AND SHTYPE='M3-Res-out' AND SHDATA LIKE 'Success%' AND SHSOURCE='CloseShipmentCoChargeAPI'
|
||||
LEFT JOIN ICM666M ON A1DELNO=A5MACPKR AND A1ONO=A5ONO AND A1PKLN=A5BRADLN
|
||||
LEFT JOIN ICM688M1 ON A4MACPKR=A5MACPKR
|
||||
WHERE A5MACPKR IN (
|
||||
SELECT DISTINCT AYMACPKR
|
||||
FROM ICM695M1
|
||||
WHERE AYSTATUS IN ('Z','z') AND AYAPR8N002 BETWEEN $reportDate2 AND $toreportDate2
|
||||
)
|
||||
AND A5CO=$COMPANY AND A5WHS=$WHS AND A5PLANT=$PLANT
|
||||
");
|
||||
|
||||
// $newItem2 = ["A5MACPKR" => 'Delivery #', "A5ONO" => 'Order #', "A4REFORD" => 'Order Type',"A5PART" => 'Part #',"A5RSVQTY" => 'Reserved',
|
||||
// "A5PACKED" => 'Packed',"CALCULATED_COLUMN" => 'Back Order Qty',"ANOTHER_CALCULATED_COLUMN" => 'Value Packed $',"A4SHSHNM" => 'Customer name',
|
||||
// "SHDT" => 'Date',"SHTIME" => 'Time',"REASON" => 'Failure Reason','A1SHCURR'=> 'Currency Code','FREIGHT'=> 'Freight'];
|
||||
|
||||
$newItem2 = ["DATECLOSED" => 'Close Date',"A5MACPKR" => 'Delivery #', "A5ONO" => 'Order #',
|
||||
"A4OFSTRM" => 'Terms',"WEIGHT" => 'Weight',"A4SCAC" => 'Carrier',"A4SHIPTYPE" => 'Mode (Parcel, Air, TL or LTL)',
|
||||
"A4REFORD" => 'Order Type',"A5PART" => 'Part #',"A5RSVQTY" => 'Reserved',
|
||||
"A5PACKED" => 'Packed',"CALCULATED_COLUMN" => 'Back Order Qty',"ANOTHER_CALCULATED_COLUMN" => 'Value Packed $',"A4SHSHNM" => 'Customer name',
|
||||
"REASON" => 'Failure Reason','A1SHCURR'=> 'Currency Code','FREIGHT'=> 'Freight'];
|
||||
|
||||
$ICM688M2Col2 = collect($ICM688M2);
|
||||
$ICM688M2Col2->prepend($newItem2);
|
||||
|
||||
# Count records before exporting to excel : Max 55K records are allowed
|
||||
$ICM688M2Count = $ICM688M2Col2->count();
|
||||
# Set Max allowed records
|
||||
$maxRecords = Config::get('arrays.maxRecCL');
|
||||
if ($ICM688M2Count>$maxRecords) {
|
||||
Log::channel('dailyCron')->info('Maximum allowed records for Excel export is: '.number_format($maxRecords).' current records: '.number_format($ICM688M2Count));
|
||||
}
|
||||
}
|
||||
else{
|
||||
$ICM688M2Col2 = collect();
|
||||
}
|
||||
|
||||
if ($ICM688M2Col2->count()>0) {
|
||||
$this->info("Saving Current Month Excel Report to Disk");
|
||||
Log::channel('dailyCron')->info("Saving Current Month Excel Report to Disk");
|
||||
# Store the File to Storage
|
||||
app(\Modules\M3\Services\SpreadsheetExport::class)->store($ICM688M2Col2, $currentMonthFile, 'publicCL');
|
||||
}
|
||||
else{
|
||||
Log::channel('dailyCron')->info("Daily Report, no records found: Nothing to save...");
|
||||
}
|
||||
|
||||
Log::channel('dailyCron')->info("Cron...End Save Orders Closed Lines to Excel");
|
||||
$this->info("Cron...End Save Orders Closed Lines to Excel");
|
||||
|
||||
}
|
||||
catch (\Throwable $th) {
|
||||
// Log::error($th);
|
||||
Log::channel('dailyCron')->error($th);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use DB;
|
||||
use Config;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Log;
|
||||
use Str;
|
||||
use Storage;
|
||||
use File;
|
||||
|
||||
|
||||
class DeleteOldLabels extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'command:DeleteOldLabelsCmd';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Delete Old Labels Command';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
//$this->info('Start CallCloseAPI...');
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOutCL'));
|
||||
ini_set('max_input_time', Config::get('arrays.PHPTimeOutCL'));
|
||||
ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOutCL'));
|
||||
ini_set('memory_limit', '1024M');
|
||||
|
||||
try {
|
||||
$this->info("Start Delete Old Labels Command...");
|
||||
Log::channel('dailyCron')->info("Cron...Start Delete Old Labels Command...");
|
||||
|
||||
$labelsDirectoryTmp = '/www/sentm3live/htdocs/labels/';
|
||||
$subFolders = ['CarrierLabel/','ContentLabel/','PackingList/']; // ,'CarrierLabel/','ContentLabel','PackingList',''
|
||||
$daysOld = 180; // Number of days to consider a file old : 180 =Six Months
|
||||
$filesToDeleteArr = [];
|
||||
|
||||
foreach ($subFolders as $key => $subFolder) {
|
||||
$labelsDirectory = $labelsDirectoryTmp.$subFolder;
|
||||
|
||||
$this->info("Getting Files From Directory: ".$labelsDirectory);
|
||||
Log::channel('dailyCron')->info("Getting Files From Directory: ".$labelsDirectory);
|
||||
|
||||
exec('find '.$labelsDirectory.' -ctime +180 -type f -exec rm {} \;');
|
||||
# exec('find '.$labelsDirectory.' -ctime +190 -type f -print | wc -l');
|
||||
}
|
||||
|
||||
$labelsFolder = $labelsDirectoryTmp;
|
||||
# Get Files from the specified Directory
|
||||
$filesToDelete = File::allFiles($labelsFolder);
|
||||
|
||||
foreach ($filesToDelete as $file) {
|
||||
$lastAccessTime = new \DateTime("@".$file->getATime());
|
||||
$now = new \DateTime();
|
||||
$diff = $now->diff($lastAccessTime)->days;
|
||||
|
||||
if ($diff >= $daysOld) {
|
||||
$this->info("File: ".$file." is Days Old: ".$diff);
|
||||
// Log::channel('dailyCron')->info("File: ".$file." is Days Old: ".$diff);
|
||||
# Add the File to Array
|
||||
$filesToDeleteArr[] = $file;
|
||||
}
|
||||
}
|
||||
|
||||
// $this->info("Files to Delete...");
|
||||
// dump($filesToDeleteArr);
|
||||
|
||||
# Delete Old Files
|
||||
File::delete($filesToDeleteArr);
|
||||
|
||||
Log::channel('dailyCron')->info("Cron...End Delete Old Labels Command...");
|
||||
$this->info("End Delete Old Labels Command...");
|
||||
|
||||
}
|
||||
catch (\Throwable $th) {
|
||||
// Log::error($th);
|
||||
Log::channel('dailyCron')->error($th);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,289 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use DB;
|
||||
use Config;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Log;
|
||||
use Str;
|
||||
|
||||
use File;
|
||||
use DateTime;
|
||||
|
||||
use Storage;
|
||||
use Cache;
|
||||
use Picqer\Barcode\BarcodeGeneratorPNG;
|
||||
use Dompdf\Dompdf;
|
||||
|
||||
use Ayeo\Barcode;
|
||||
use PDF;
|
||||
use App;
|
||||
|
||||
use Zebra\Client;
|
||||
use Zebra\Zpl\Image;
|
||||
use Zebra\Zpl\Builder;
|
||||
use Zebra\Zpl\GdDecoder;
|
||||
|
||||
class GenerateGS1Cmd extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'command:GenerateGS1Cmd {user?} {--gsarray=}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Generate GS1-128 Label';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
//$this->info('Start CallCloseAPI...');
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOutCL'));
|
||||
ini_set('max_input_time', Config::get('arrays.PHPTimeOutCL'));
|
||||
ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOutCL'));
|
||||
ini_set('memory_limit', '1024M');
|
||||
|
||||
try {
|
||||
$this->info('>>> Run GS1 Label creation Command...');
|
||||
Log::channel('LabelCron')->info(">>> Run GS1 Label creation Command...");
|
||||
|
||||
# Get the Calling User
|
||||
$userId = $this->argument('user');
|
||||
$SHUSER = isset($userId) ? $userId : (m3_user() !== '' ? Str::upper(trim(m3_user())) : 'TWOSHIP');
|
||||
$this->info('User: '.$SHUSER);
|
||||
|
||||
# Get Manifest Array
|
||||
$GSArray1 = $this->option('gsarray');
|
||||
$GSArray = json_decode($GSArray1, true);
|
||||
// dump($GSArray);
|
||||
|
||||
# MAK : Used for debug only
|
||||
$GSArray = ["Macpkr"=> "55555","Recipient_Address1"=>"9571 Pan American DR", "Recipient_Address2"=>"C/O AEE Solar","Recipient_City"=>"El Paso",
|
||||
"Recipient_CompanyName"=>"SNAPRACK EL PASO PRODUCTION","Recipient_CountryCode"=>"US","Recipient_PostalCode"=>"79927","Recipient_State"=>"TX",
|
||||
"Sender_Address1"=>"6800 Arnold Miller Pkwy","Sender_Address2"=>"","Sender_City"=>"Solon",
|
||||
"Sender_CompanyName"=>"Erico International","Sender_Country"=>"US","Sender_PostalCode"=>"44139","Sender_State"=>"OH",
|
||||
"CarrierName"=>"R&L Carriers","trackingno"=>"306539838","BOLnumber"=>"693103848064454","ShipmentPONumber"=>"4523039092",
|
||||
"PackagesArray"=> ["package 1" , "package 2"]
|
||||
];
|
||||
|
||||
|
||||
if ($SHUSER!='') {
|
||||
# Get User CO & WH from Table ICM428M
|
||||
$ICM428M = DB::connection(config('m3.connection', 'pgsql'))->table('icm428m')
|
||||
->select('R428US','R428CO', 'R428WH','R428PL')
|
||||
->where('R428US','=',$SHUSER)
|
||||
->first();
|
||||
|
||||
$R428US = isset($ICM428M->R428US) ? $ICM428M->R428US : ''; # User
|
||||
$COMPANY = isset($ICM428M->R428CO) ? $ICM428M->R428CO : ''; # Company
|
||||
$PLANT = isset($ICM428M->R428PL) ? $ICM428M->R428PL : ''; # Plant
|
||||
$WHS = isset($ICM428M->R428WH) ? $ICM428M->R428WH : ''; # WareHouse
|
||||
|
||||
$Macpkr = $GSArray['Macpkr'];
|
||||
$packageType = '0';
|
||||
$manufactID = '0826528'; # MAK : get ID from Nvent and save to Config File
|
||||
$total_length = 9;
|
||||
|
||||
$html = '
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
.border_btm {
|
||||
border-bottom: 1px solid;
|
||||
}
|
||||
.border_rght {
|
||||
border-right: 1px solid;
|
||||
}
|
||||
|
||||
.margin_t {
|
||||
padding-top : 10px;
|
||||
}
|
||||
|
||||
.align_lft {
|
||||
text-align: left;
|
||||
}
|
||||
.align_center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@page { margin: 5px; }
|
||||
body { margin: 0px; }
|
||||
</style>
|
||||
</head>
|
||||
<body style="font-family: Arial, sans-serif;">';
|
||||
|
||||
# Get number of Pallets
|
||||
$packageCount = count($GSArray['PackagesArray']);
|
||||
$packageNum = 1;
|
||||
foreach ($GSArray['PackagesArray'] as $key => $value) {
|
||||
$table_style = $packageNum < $packageCount ? ' style="page-break-after: always;" ' : '';
|
||||
|
||||
if (Cache::has('GS1SEQUENCE')) {
|
||||
$GS1SEQUENCE = Cache::get('GS1SEQUENCE');
|
||||
$GS1SEQUENCE++;
|
||||
$GS1SEQUENCEID = str_pad($GS1SEQUENCE, $total_length, "0", STR_PAD_LEFT);
|
||||
}
|
||||
# Box Number Not Found Get it from DB
|
||||
else{
|
||||
$GS1SEQUENCE = 1;
|
||||
$GS1SEQUENCEID = str_pad($GS1SEQUENCE, $total_length, "0", STR_PAD_LEFT);
|
||||
}
|
||||
Cache::forever('GS1SEQUENCE', $GS1SEQUENCEID);
|
||||
$this->info(">>> GS1 sequence Id: ".$GS1SEQUENCEID);
|
||||
|
||||
$gs1_128_bc_1 = '00' .$packageType . $manufactID . $GS1SEQUENCEID;
|
||||
|
||||
# Calculate Check Digit
|
||||
$digits = str_split($gs1_128_bc_1);
|
||||
$sum = 0;
|
||||
$length = count($digits);
|
||||
|
||||
# Loop through each digit starting from the right
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$digit = $digits[$length - $i - 1];
|
||||
# Assign a weight of 3 or 1 alternately
|
||||
$weight = ($i % 2 == 0) ? 3 : 1;
|
||||
# Add the product of the digit and its weight to the sum
|
||||
$sum += $digit * $weight;
|
||||
}
|
||||
# Calculate the remainder when sum is divided by 10
|
||||
$remainder = $sum % 10;
|
||||
# If remainder is 0, check digit is 0; otherwise, subtract remainder from 10
|
||||
$checkDigit = ($remainder == 0) ? 0 : 10 - $remainder;
|
||||
|
||||
$gs1_128_bc = $gs1_128_bc_1 . $checkDigit;
|
||||
$gs1_128_bc_desc = '(00)' .$packageType . $manufactID . $GS1SEQUENCEID .$checkDigit;
|
||||
|
||||
$data = [
|
||||
'ship_to' => $GSArray["Recipient_CompanyName"].'<br>'.$GSArray["Recipient_Address1"].'<br>'.
|
||||
$GSArray["Recipient_City"].','. $GSArray["Recipient_State"]
|
||||
.'<br>'.$GSArray["Recipient_PostalCode"] ,
|
||||
'from' => $GSArray["Sender_CompanyName"].'<br>'.$GSArray["Sender_Address1"].'<br>'.
|
||||
$GSArray["Sender_City"].','. $GSArray["Sender_State"]
|
||||
.'<br>'.$GSArray["Sender_PostalCode"] ,
|
||||
'ship_to_lbl' => '420'.$GSArray["Recipient_PostalCode"],
|
||||
'ship_to_desc' => '(420)'.$GSArray["Recipient_PostalCode"],
|
||||
'pro' => '190071217845706',
|
||||
'item_number' => '10000B',
|
||||
'upc' => '098506095310',
|
||||
'quantity' => '1',
|
||||
'serial_shipping_container' => $gs1_128_bc_desc
|
||||
];
|
||||
|
||||
# Initialize barcode generator
|
||||
$generator = new BarcodeGeneratorPNG();
|
||||
|
||||
# Generate barcodes
|
||||
$shipToPostalCodeBarcode = $generator->getBarcode($data['ship_to_lbl'], $generator::TYPE_CODE_128);
|
||||
$serialShippingContainerBarcode = $generator->getBarcode($data['serial_shipping_container'], $generator::TYPE_CODE_128, 2 ,50);
|
||||
|
||||
# HTML content for the label
|
||||
$html .= '
|
||||
<table '.$table_style.'>
|
||||
<tr>
|
||||
<td colspan="2" class="border_btm border_rght align_lft">
|
||||
FROM:<br>' . $data['from'] . '
|
||||
</td>
|
||||
<td colspan="2" class="border_btm align_lft">
|
||||
SHIP TO:<br>' . $data['ship_to'] . '
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3" class="border_btm border_rght margin_t align_center">
|
||||
<img src="data:image/png;base64,' . base64_encode($shipToPostalCodeBarcode) . '"> <br>
|
||||
' . $data['ship_to_desc'] . '
|
||||
</td>
|
||||
<td class="border_btm margin_t align_lft">
|
||||
Carrier: '.$GSArray["CarrierName"].' <br>
|
||||
PRO #: '.$GSArray["ShipmentPONumber"].' <br>
|
||||
B/L #: '.$GSArray["BOLnumber"].'
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="border_btm margin_t align_lft border_rght">
|
||||
PURCHASE ORDER: '.$GSArray["Macpkr"].' <br>
|
||||
Vendor: ' . $manufactID . '
|
||||
</td>
|
||||
<td colspan="2" class="border_btm margin_t align_center">
|
||||
Pallet # : '.$packageNum.' of '.$packageCount.'
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4" style="text-align: center;" class="margin_t">
|
||||
<img src="data:image/png;base64,' . base64_encode($serialShippingContainerBarcode) . '"><br>
|
||||
' . $data['serial_shipping_container'] . '
|
||||
</td>
|
||||
</tr>
|
||||
</table>';
|
||||
|
||||
$packageNum++;
|
||||
}
|
||||
|
||||
$html .='</body> </html>';
|
||||
// dump($html);
|
||||
// App::call('App\Http\Controllers\utilitiesContoller@generateGS128');
|
||||
|
||||
ob_start();
|
||||
|
||||
# Initialize Dompdf
|
||||
$dompdf = new Dompdf();
|
||||
$dompdf->loadHtml($html);
|
||||
$dompdf->setPaper('a6', 'portrait');
|
||||
# Render the HTML as PDF
|
||||
$dompdf->render();
|
||||
|
||||
# Output the generated PDF to Browser
|
||||
// $dompdf->stream();
|
||||
|
||||
$pdfContent = $dompdf->output();
|
||||
// dump($pdfContent);
|
||||
|
||||
$labelsPath = Config::get('arrays.PdfPath');
|
||||
# Put the PDF in labels/CarrierLabel
|
||||
$GSFolder = "GSLabel";
|
||||
$carrierFileName = $GSFolder.'_'.$Macpkr.'_'.$COMPANY.'_'.$WHS;
|
||||
file_put_contents($labelsPath.$GSFolder.'/'.$carrierFileName.'.pdf',$pdfContent);
|
||||
|
||||
# Check if the PDF was generated correctly
|
||||
// if (!file_exists($tempPdfPath) || filesize($tempPdfPath) === 0) {
|
||||
// throw new Exception('PDF generation failed.');
|
||||
// }
|
||||
|
||||
ob_end_clean();
|
||||
}
|
||||
|
||||
Log::channel('LabelCron')->info("<<< GS1-128...End of Label Creation");
|
||||
$this->info("<<< GS1-128...End of Label Creation");
|
||||
|
||||
}
|
||||
catch (\Throwable $th) {
|
||||
// Log::error($th);
|
||||
Log::channel('LabelCron')->error($th);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use DB;
|
||||
use Config;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Log;
|
||||
use Str;
|
||||
|
||||
use Modules\M3\Http\Controllers\utilitiesContoller;
|
||||
|
||||
class UtilitiesCmd extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'command:UtilitiesCmd';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Utilities Command';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
//$this->info('Start CallCloseAPI...');
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOutCL'));
|
||||
ini_set('max_input_time', Config::get('arrays.PHPTimeOutCL'));
|
||||
ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOutCL'));
|
||||
ini_set('memory_limit', '1024M');
|
||||
|
||||
try {
|
||||
$this->info("Start Utilities Command...");
|
||||
|
||||
// $this->info('User: '.$SHUSER);
|
||||
$myRequest = new Request();
|
||||
utilitiesContoller::fixICM799MSentPKR($myRequest);
|
||||
|
||||
// Log::channel('dailyCron')->info("Cron...End Save Orders Closed Lines to Excel");
|
||||
$this->info("End Utilities Command...");
|
||||
|
||||
}
|
||||
catch (\Throwable $th) {
|
||||
// Log::error($th);
|
||||
Log::channel('dailyCron')->error($th);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use DB;
|
||||
use Config;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Log;
|
||||
use Str;
|
||||
|
||||
|
||||
use Storage;
|
||||
|
||||
class WHSMetricsSaveXls extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'command:WHSMetricsSaveXls {user?} {co?} {whs?} {pl?}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Save WHS Metrics to Excel';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
//$this->info('Start CallCloseAPI...');
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOutCL'));
|
||||
ini_set('max_input_time', Config::get('arrays.PHPTimeOutCL'));
|
||||
ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOutCL'));
|
||||
ini_set('memory_limit', '1024M');
|
||||
|
||||
try {
|
||||
Log::channel('dailyCron')->info("Cron...Start Save WHS Metrics to Excel");
|
||||
|
||||
# Get the Calling User
|
||||
$userId = $this->argument('user');
|
||||
$SHUSER = isset($userId) ? $userId : (m3_user() !== '' ? Str::upper(trim(m3_user())) : '');
|
||||
|
||||
$CO = $this->argument('co');
|
||||
// $COMPANY = isset($CO) ? trim($CO) : '110';
|
||||
$COMPANY = '110';
|
||||
$PWHS = $this->argument('whs');
|
||||
// $WHS = isset($PWHS) ? trim($PWHS) : '321';
|
||||
$WHS = '321';
|
||||
$PPL = $this->argument('pl');
|
||||
// $PLANT = isset($PPL) ? trim($PPL) : '143';
|
||||
$PLANT = '143';
|
||||
|
||||
$date = new \DateTime();
|
||||
$DateToday = $date->format('Y-m-d');
|
||||
|
||||
# Define File Name
|
||||
$whsPerfFile = 'WhsPerf/'.$WHS.'/WhsPerfMetrics_'.$DateToday.'-'.$WHS.'.xlsx';
|
||||
Log::channel('dailyCron')->info(">>> File Name:");
|
||||
Log::channel('dailyCron')->info($whsPerfFile);
|
||||
|
||||
$this->info("Generate Today WHS Performance Report...");
|
||||
|
||||
if( $COMPANY!='' && $WHS!='' && $PLANT!='' ){
|
||||
# Get Header Content
|
||||
$ICM700MHeadSel = DB::connection(config('m3.connection', 'pgsql'))
|
||||
->select("
|
||||
WITH TEMPFILE AS (
|
||||
SELECT A.*,A4TPCKWGHT,A4NOPICLNS,A4PICKSTS,
|
||||
CASE WHEN UPPER(A4PICKSTS)<>'A' THEN 'Open' ELSE 'Closed' END AS STATUS,
|
||||
CASE WHEN A4TPCKWGHT>16000 THEN 'FTL' ELSE A4SHIPTYPE END AS A4SHIPTYPE,
|
||||
(SELECT SUM(A5RSVQTY*A5SLUNPR) FROM ICM688M2 WHERE A4MACPKR=A5MACPKR) AS DOLLARS
|
||||
FROM ICM700M A LEFT JOIN ICM688M1 B ON A4MACPKR=A3MACPKR
|
||||
WHERE A3MSMTDATE= (SELECT MAX(A3MSMTDATE) FROM ICM700M) AND A3CO='$COMPANY' AND A3WHS='$WHS' AND A3PLT='$PLANT'
|
||||
)
|
||||
SELECT A4SHIPTYPE,STATUS,SOURCE,COUNT(*) AS PICKERS, SUM(A4TPCKWGHT) AS WEIGHT,SUM(A4NOPICLNS) AS LINES,SUM(DOLLARS) AS DOLLARS
|
||||
FROM TEMPFILE
|
||||
GROUP BY A4SHIPTYPE,STATUS,SOURCE
|
||||
ORDER BY 1,3,2
|
||||
");
|
||||
// dd($ICM700MHeadSel);
|
||||
|
||||
$newItem = ["A4SHIPTYPE" => 'Method', "STATUS" => 'Status', "SOURCE" => 'Source', "PICKERS" => 'Pickers',
|
||||
"WEIGHT" => 'Weight', "LINES" => 'Lines', "DOLLARS" => 'Dollars'];
|
||||
|
||||
# Trim All values
|
||||
$ICM700MHeadCol = collect($ICM700MHeadSel)->map(function ($item) {
|
||||
foreach ($item as $key => $value) {
|
||||
if (is_string($value)) {
|
||||
$item->{$key} = trim($value);
|
||||
}
|
||||
}
|
||||
return $item;
|
||||
});
|
||||
# Prepend Header to Collection
|
||||
$ICM700MHeadCol->prepend($newItem);
|
||||
|
||||
// $this->info($ICM700MHeadCol);
|
||||
// Log::channel('dailyCron')->info(">>> Header Content");
|
||||
// Log::channel('dailyCron')->info($ICM700MHeadCol);
|
||||
|
||||
# Count records before exporting to excel
|
||||
$ICM700MHeadCount = $ICM700MHeadCol->count();
|
||||
|
||||
# Get Details Content
|
||||
$ICM700MDetailsSel = DB::connection(config('m3.connection', 'pgsql'))
|
||||
->select("
|
||||
WITH TEMPFILE AS (
|
||||
SELECT A3CO,A3WHS,A3PLT,A3MACPKR,A4PICKCRTS,SOURCE,
|
||||
(SELECT TO_TIMESTAMP(CAST(SHDT AS TEXT) || ' ' || CAST(SHTIME AS TEXT), 'YYYY-MM-DD HH24:MI:SS') FROM ICM699M WHERE SHMACPKR=A4MACPKR AND SHTYPE='Lisnr-Hold' ORDER BY SHDT DESC, SHTIME DESC FETCH FIRST 1 ROWS ONLY) AS CARRIERASSIGNED,
|
||||
A4ONO,A4SHSHNM,A4SCAC,A42SSVCNAM,A4PICKSTS,
|
||||
CASE WHEN UPPER(A4PICKSTS)<>'A' THEN 'Open' ELSE 'Closed' END AS STATUS,
|
||||
CASE WHEN A4TPCKWGHT>16000 THEN 'FTL' ELSE A4SHIPTYPE END AS A4SHIPTYPE,
|
||||
A4TPCKWGHT,A4NOPICLNS,
|
||||
(SELECT SUM(A5RSVQTY*A5SLUNPR) FROM ICM688M2 WHERE A4MACPKR=A5MACPKR) AS DOLLARS
|
||||
FROM ICM700M A
|
||||
LEFT JOIN ICM688M1 B ON A4MACPKR=A3MACPKR
|
||||
WHERE A3MSMTDATE=(SELECT MAX(A3MSMTDATE) FROM ICM700M) AND A3CO='$COMPANY' AND A3WHS='$WHS' AND A3PLT='$PLANT'
|
||||
)
|
||||
SELECT * FROM TEMPFILE
|
||||
");
|
||||
|
||||
$newItem2 = ["A3CO" => 'Co', "A3WHS" => 'Whs', "A3PLT" => 'Plt', "A3MACPKR" => 'Delivery No', "A4PICKCRTS" => 'Date Time Arrived in Sentinel',
|
||||
"SOURCE" => 'Source', "CARRIERASSIGNED" => 'Date carrier Assigned', "A4ONO" => 'Order No', "A4SHSHNM" => 'Customer name',"A4SCAC" => 'Carrier',
|
||||
"A42SSVCNAM" => 'Service', "A4PICKSTS" => 'Picker Status', "STATUS" => 'Open or Closed', "A4SHIPTYPE" => 'Method',
|
||||
"A4TPCKWGHT" => 'Weight', "A4NOPICLNS" => 'Lines' , "DOLLARS" => 'Dollars' ];
|
||||
# Trim all values
|
||||
$ICM700MDetailsCol = collect($ICM700MDetailsSel)->map(function ($item) {
|
||||
foreach ($item as $key => $value) {
|
||||
if (is_string($value)) {
|
||||
$item->{$key} = trim($value);
|
||||
}
|
||||
}
|
||||
return $item;
|
||||
});
|
||||
|
||||
# Prepend Header
|
||||
$ICM700MDetailsCol->prepend($newItem2);
|
||||
|
||||
# Count records before exporting to excel
|
||||
$ICM700MDetailsCount = $ICM700MDetailsCol->count();
|
||||
}
|
||||
else{
|
||||
$ICM700MDetailsCol = collect();
|
||||
}
|
||||
// Log::channel('dailyCron')->info(">>> Detail Content");
|
||||
// Log::channel('dailyCron')->info($ICM700MDetailsCol);
|
||||
|
||||
# Save Head and Details to XLS file
|
||||
if ($ICM700MHeadCount>0 && $ICM700MDetailsCount>0) {
|
||||
$this->info("Saving Today WHS Performance Report to Disk...");
|
||||
Log::channel('dailyCron')->info("Saving Today WHS Performance Report to Disk...");
|
||||
|
||||
# Store both collections in one XLSX workbook using Core's PhpSpreadsheet dependency.
|
||||
app(\Modules\M3\Services\SpreadsheetExport::class)->storeSheets([
|
||||
'Summary' => $ICM700MHeadCol,
|
||||
'Details' => $ICM700MDetailsCol,
|
||||
], $whsPerfFile, 'publicLabels');
|
||||
|
||||
|
||||
}
|
||||
else{
|
||||
Log::channel('dailyCron')->info("Today WHS Performance Report, no records found: Nothing to save...");
|
||||
}
|
||||
|
||||
Log::channel('dailyCron')->info("Cron...End Save Today WHS Performance Report to Excel");
|
||||
$this->info("Cron...End Save Today WHS Performance Report to Excel");
|
||||
|
||||
}
|
||||
catch (\Throwable $th) {
|
||||
// Log::error($th);
|
||||
Log::channel('dailyCron')->error($th);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::connection(config('m3.connection', 'pgsql'))->create('m3_program_requests', function (Blueprint $table): void {
|
||||
$table->bigIncrements('id');
|
||||
$table->string('type', 20);
|
||||
$table->string('operation', 255);
|
||||
$table->string('library', 255)->nullable();
|
||||
$table->jsonb('payload')->nullable();
|
||||
$table->string('requested_by', 255)->nullable();
|
||||
$table->string('status', 30)->default('pending')->index();
|
||||
$table->text('result')->nullable();
|
||||
$table->text('error')->nullable();
|
||||
$table->timestamp('processed_at')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::connection(config('m3.connection', 'pgsql'))->dropIfExists('m3_program_requests');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
// app/Helpers/USStates.php
|
||||
|
||||
namespace Modules\M3\Helpers;
|
||||
|
||||
class CAProvinces
|
||||
{
|
||||
public static function all() {
|
||||
return [
|
||||
'AB' => 'Alberta',
|
||||
'BC' => 'British Columbia',
|
||||
'MB' => 'Manitoba',
|
||||
'NB' => 'New Brunswick',
|
||||
'NL' => 'Newfoundland and Labrador',
|
||||
'NS' => 'Nova Scotia',
|
||||
'NT' => 'Northwest Territories',
|
||||
'NU' => 'Nunavut',
|
||||
'ON' => 'Ontario',
|
||||
'PE' => 'Prince Edward Island',
|
||||
'QC' => 'Quebec',
|
||||
'SK' => 'Saskatchewan',
|
||||
'YT' => 'Yukon'
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,385 @@
|
||||
<?php
|
||||
use Modules\M3\Support\ModuleInfo;
|
||||
|
||||
if (! function_exists('m3_feature_enabled')) {
|
||||
/**
|
||||
* Check if a feature is enabled in the config.
|
||||
*/
|
||||
function m3_feature_enabled(string $key): bool
|
||||
namespace Modules\M3\Helpers;
|
||||
|
||||
use Gate;
|
||||
use DB;
|
||||
use Config;
|
||||
use Form;
|
||||
use Auth;
|
||||
use Redirect;
|
||||
use Mail;
|
||||
use Log;
|
||||
use Cache;
|
||||
use Str;
|
||||
use File;
|
||||
|
||||
class Helper
|
||||
{
|
||||
# Check M3 API Token
|
||||
public static function checkReceiveToken(){
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOut'));
|
||||
|
||||
# Clear Cache
|
||||
// Cache::forget('token');
|
||||
# Check if cached Token is still Valid
|
||||
$token = Cache::get('token');
|
||||
|
||||
if (isset($token)) {
|
||||
$IonToken = $token;
|
||||
// Log::info("Cached Token: ".$IonToken);
|
||||
}
|
||||
else{
|
||||
### CURL
|
||||
### Generate Token
|
||||
$curl = curl_init();
|
||||
|
||||
curl_setopt_array($curl, array(
|
||||
CURLOPT_URL => env('ENDPOINTURLSSO').env('URLTOKEN'),
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_ENCODING => '',
|
||||
CURLOPT_MAXREDIRS => 10,
|
||||
CURLOPT_TIMEOUT => 0,
|
||||
CURLOPT_FOLLOWLOCATION => true,
|
||||
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
||||
CURLOPT_CUSTOMREQUEST => 'POST',
|
||||
CURLOPT_POSTFIELDS => 'grant_type='.env('GRANT_TYPE').'&password='.env('PASSWORD').'&username='.env('USERNAME').'&client_secret='.env('CLIENT_SECRET').
|
||||
'&client_id='.env('CLIENT_ID'),
|
||||
CURLOPT_HTTPHEADER => array(
|
||||
'Content-Type: application/x-www-form-urlencoded',
|
||||
'charset:UTF-8',
|
||||
'Accept: application/json'
|
||||
),
|
||||
));
|
||||
|
||||
$response = curl_exec($curl);
|
||||
// dd($response);
|
||||
$responseJ = json_decode($response);
|
||||
|
||||
if($response === false ){
|
||||
return response()->json([
|
||||
'code' =>'400',
|
||||
'status' =>'Failed',
|
||||
'message' =>'Token Verification Error...'.curl_error($curl)
|
||||
]);
|
||||
}
|
||||
else if(isset($responseJ->access_token) ){
|
||||
$IonToken = $responseJ->access_token;
|
||||
// Log::info("New Token: " . $IonToken);
|
||||
|
||||
Cache::put('token', $IonToken, now()->addMinutes(59));
|
||||
}
|
||||
else{
|
||||
// dd($response);
|
||||
return response()->json([
|
||||
'code' =>'400',
|
||||
'status' =>'Failed',
|
||||
'message' =>'Token Verification Error...M3 response:'.$response
|
||||
]);
|
||||
}
|
||||
|
||||
curl_close($curl);
|
||||
}
|
||||
|
||||
return $IonToken;
|
||||
// return response()->json([
|
||||
// 'code' => '200',
|
||||
// 'token' => $IonToken
|
||||
// ]);
|
||||
}
|
||||
|
||||
# Check M3 API Token V2
|
||||
public static function checkReceiveTokenV2(){
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOut'));
|
||||
|
||||
# Clear Cache
|
||||
// Cache::forget('token');
|
||||
|
||||
# Check if cached Token is still Valid
|
||||
$token = Cache::get('token');
|
||||
|
||||
if (isset($token)) {
|
||||
$IonToken = $token;
|
||||
// Log::info("Cached Token: ".$IonToken);
|
||||
}
|
||||
else{
|
||||
### CURL
|
||||
### Generate Token
|
||||
$curl = curl_init();
|
||||
|
||||
curl_setopt_array($curl, array(
|
||||
CURLOPT_URL => env('ENDPOINTURLSSO').env('URLTOKEN'),
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_ENCODING => '',
|
||||
CURLOPT_MAXREDIRS => 10,
|
||||
CURLOPT_TIMEOUT => 0,
|
||||
CURLOPT_FOLLOWLOCATION => true,
|
||||
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
||||
CURLOPT_CUSTOMREQUEST => 'POST',
|
||||
CURLOPT_POSTFIELDS => 'grant_type='.env('GRANT_TYPE').'&password='.env('PASSWORD').'&username='.env('USERNAME').'&client_secret='.env('CLIENT_SECRET').
|
||||
'&client_id='.env('CLIENT_ID'),
|
||||
CURLOPT_HTTPHEADER => array(
|
||||
'Content-Type: application/x-www-form-urlencoded',
|
||||
'charset:UTF-8',
|
||||
'Accept: application/json'
|
||||
),
|
||||
));
|
||||
|
||||
$response = curl_exec($curl);
|
||||
// dd($response);
|
||||
$responseJ = json_decode($response);
|
||||
curl_close($curl);
|
||||
|
||||
if($response === false ){
|
||||
# Clear Cache
|
||||
Cache::forget('token');
|
||||
# Return Error
|
||||
return response()->json([
|
||||
'code' =>'400',
|
||||
'status' =>'Failed',
|
||||
'message' =>'Token Verification Error...'.curl_error($curl)
|
||||
]);
|
||||
}
|
||||
else if(isset($responseJ->access_token) ){
|
||||
$IonToken = $responseJ->access_token;
|
||||
// Log::info("New Token: " . $IonToken);
|
||||
Cache::put('token', $IonToken, now()->addMinutes(59));
|
||||
}
|
||||
else{
|
||||
# Clear Cache
|
||||
Cache::forget('token');
|
||||
return response()->json([
|
||||
'code' =>'400',
|
||||
'status' =>'Failed',
|
||||
'message' =>'Token Verification Error...M3 response:'.$response
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// return $IonToken;
|
||||
return response()->json([
|
||||
'code' => '200',
|
||||
'token' => $IonToken
|
||||
]);
|
||||
}
|
||||
|
||||
# Read M3 JSON and Analyse it for Errors
|
||||
public static function checkM3Errors($responseResult){
|
||||
// dd($responseResult);
|
||||
# M3 Response Types
|
||||
$M3TypesResponse = ['CloseShipment','Move','COCharge','Replenish','MoveDock'];
|
||||
# CloseShipment Types And Contents
|
||||
$M3CloseShipmentResp = ['AddPackage','PickingListClose','TrailerNo','TrackingNo','ContentLabel', 'DeliveryNote','ShipLabel'];
|
||||
// 'ContentLabel', 'DeliveryNote','ShipLabel'
|
||||
$ErrorMessages = '';
|
||||
|
||||
$typesErrors =0;
|
||||
|
||||
foreach ($M3TypesResponse as $key => $Type) {
|
||||
// dump($responseResult->$Type);
|
||||
if ($Type=='CloseShipment') {
|
||||
// dump($Type);
|
||||
$CloseShipmentErr = 0;
|
||||
$M3RespClose = $responseResult->$Type;
|
||||
foreach ($M3CloseShipmentResp as $key => $closeType) {
|
||||
$ErrorMessage = $M3RespClose->$closeType->ErrorMessage;
|
||||
$ErrorMessage = $ErrorMessage=="" ? "" : $ErrorMessage;
|
||||
$Result = $M3RespClose->$closeType->Result;
|
||||
$ResultT = $M3RespClose->$closeType->Result;
|
||||
$Result = $Result=="N/A" || $Result=="OK" ? "" : $Result;
|
||||
if ($ErrorMessage!='' || $Result!='') {
|
||||
$ErrorMessages .= $closeType.'-'.$Result.'-'.$ErrorMessage.' ';
|
||||
}
|
||||
// dump($closeType);// dump($ErrorMessage);// dump($Result);
|
||||
|
||||
if ($ResultT=="N/A") {
|
||||
$CloseShipmentErr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if($Type=='MoveDock'){
|
||||
$MoveDockRes = isset($responseResult->$Type->Move) ? $responseResult->$Type->Move : '';
|
||||
$ErrorMessage = isset($MoveDockRes->ErrorMessage) ? $MoveDockRes->ErrorMessage :'';
|
||||
$ErrorMessage = $ErrorMessage=="" ? "" : $ErrorMessage;
|
||||
$Result = isset($MoveDockRes->Result) ? $MoveDockRes->Result : "";
|
||||
$ResultT = $Result;
|
||||
$Result = $Result=="N/A" || $Result=="OK" ? "" : $Result;
|
||||
if ($ErrorMessage!='' || $Result!='') {
|
||||
$ErrorMessages .= $Type.'-'.$Result.'-'.$ErrorMessage.' ';
|
||||
}
|
||||
// dump($Type);// dump($ErrorMessage);// dump($Result);// dump($responseResult->$Type);
|
||||
if ($ResultT=="N/A") {
|
||||
$typesErrors++;
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
$ErrorMessage = isset($responseResult->$Type->ErrorMessage) ? $responseResult->$Type->ErrorMessage :'';
|
||||
$ErrorMessage = $ErrorMessage=="" ? "" : $ErrorMessage;
|
||||
$Result = isset($responseResult->$Type->Result) ? $responseResult->$Type->Result : "";
|
||||
$ResultT = $Result;
|
||||
$Result = $Result=="N/A" || $Result=="OK" ? "" : $Result;
|
||||
if ($ErrorMessage!='' || $Result!='') {
|
||||
$ErrorMessages .= $Type.'-'.$Result.'-'.$ErrorMessage.' ';
|
||||
}
|
||||
// dump($Type); // dump($ErrorMessage); // dump($Result); // dump($responseResult->$Type);
|
||||
if ($ResultT=="N/A") {
|
||||
$typesErrors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// dd($ErrorMessages);
|
||||
|
||||
if ($CloseShipmentErr == count($M3CloseShipmentResp) && $typesErrors == count($M3TypesResponse)-1) {
|
||||
$ErrorMessages .= '-M3 did not call any method or type ';
|
||||
}
|
||||
|
||||
return $ErrorMessages;
|
||||
}
|
||||
|
||||
# Log All Success And Error to ICM699M
|
||||
public static function logToICM699M($data){
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOut'));
|
||||
|
||||
$insertSQL = DB::connection(config('m3.connection', 'pgsql'))->table('ICM699M')->insert($data);
|
||||
// dump($data);
|
||||
// dump($insertSQL);
|
||||
}
|
||||
|
||||
# Get Substring in string between 2 Substrings
|
||||
public static function getSubstringBetween($string, $start, $end) {
|
||||
$startPos = strpos($string, $start);
|
||||
if ($startPos === false) {
|
||||
return '';
|
||||
}
|
||||
$endPos = strpos($string, $end, $startPos + strlen($start));
|
||||
if ($endPos === false) {
|
||||
return '';
|
||||
}
|
||||
$substring = substr($string, $startPos + strlen($start), $endPos - ($startPos + strlen($start)));
|
||||
return $substring;
|
||||
}
|
||||
|
||||
public static function checkLength($JSONL,$DBL,$TYPE)
|
||||
{
|
||||
return (bool) config(ModuleInfo::nameLower().".features.{$key}", false);
|
||||
# Check type
|
||||
$JSONType = gettype($JSONL);
|
||||
|
||||
switch ($JSONType) {
|
||||
case 'string':
|
||||
$JSONTypeConv = 'string';
|
||||
break;
|
||||
case 'double':
|
||||
$JSONTypeConv = 'number';
|
||||
break;
|
||||
case 'integer':
|
||||
$JSONTypeConv = 'number';
|
||||
break;
|
||||
default:
|
||||
$JSONTypeConv = 'null';
|
||||
break;
|
||||
}
|
||||
|
||||
$TYPE = $TYPE == 'integer' || $TYPE == 'DEC' ? 'number' : $TYPE;
|
||||
// Log::info( $JSONL .' L: '. strlen($JSONL) .' DBL: '. $DBL .' Type:'.$JSONType.':'.$TYPE );
|
||||
|
||||
// Check Json Field should be < DB Field
|
||||
$LengthOK[413] = ( strlen($JSONL) <= $DBL ) ? true : false ;
|
||||
// Empty Fields
|
||||
$LengthOK[411] = true; //!empty($JSONL) ? true : false ;
|
||||
// Wrong Types
|
||||
$LengthOK[417] = true; //$JSONTypeConv == $TYPE ? true : false ;
|
||||
// Log::info($LengthOK);
|
||||
|
||||
return $LengthOK;
|
||||
}
|
||||
|
||||
public static function sanityzeString($StrTosanityze)
|
||||
{
|
||||
$badChars = Config::get('arrays.BadChars');
|
||||
|
||||
$goodString = trim($StrTosanityze);
|
||||
$goodString = str_replace("'", "",$goodString);
|
||||
$goodString = preg_replace('/\x{f0e0}/u', '', $goodString);
|
||||
$goodString = preg_replace('/\\\\u201[0-9A-F]+/i', '', $goodString);
|
||||
$goodString = str_replace($badChars, '',$goodString);
|
||||
$goodString = iconv("UTF-8", "ISO-8859-1//IGNORE", $goodString);
|
||||
$goodString = iconv("ISO-8859-1", "UTF-8", $goodString);
|
||||
|
||||
# MAK : New Automatic Detection for encoding and conversion
|
||||
# Detect the encoding
|
||||
// $encoding = mb_detect_encoding($goodString, mb_list_encodings(), true);
|
||||
// Log::info($goodString);
|
||||
|
||||
# If encoding is detected, convert the string
|
||||
// if ($encoding !== false) {
|
||||
// // Log::info($encoding);
|
||||
// // Log::info($goodString);
|
||||
|
||||
// $goodString = mb_convert_encoding($goodString, "UTF-8", $encoding);
|
||||
// } else {
|
||||
// $goodString = "";
|
||||
// }
|
||||
|
||||
// dump($goodString);
|
||||
return $goodString;
|
||||
}
|
||||
|
||||
# Remove Duplicate SubString
|
||||
public static function removeDuplicateSubstrings($str) {
|
||||
$result = '';
|
||||
$seenPhrases = [];
|
||||
|
||||
$phrases = explode(' ', $str);
|
||||
foreach ($phrases as $phrase) {
|
||||
if (!in_array($phrase, $seenPhrases)) {
|
||||
$result .= $phrase . ' ';
|
||||
$seenPhrases[] = $phrase;
|
||||
}
|
||||
}
|
||||
|
||||
return trim($result);
|
||||
}
|
||||
|
||||
public static function getUserCOWHSPLT(){
|
||||
$defaults = [
|
||||
'UserCO' => '',
|
||||
'UserWHS' => '',
|
||||
'UserPL' => '',
|
||||
];
|
||||
|
||||
$loggedUser = strtoupper(trim((string) m3_user()));
|
||||
if ($loggedUser === '') {
|
||||
return $defaults;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!\Illuminate\Support\Facades\Schema::connection(config('m3.connection', 'pgsql'))->hasTable('icm428m')) {
|
||||
return $defaults;
|
||||
}
|
||||
|
||||
$user = DB::connection(config('m3.connection', 'pgsql'))->table('icm428m')
|
||||
->select('R428US', 'R428ADMUSR', 'R428PWRUSR', 'R428CO', 'R428PL', 'R428WH', 'R42811A', 'R42821A')
|
||||
->where('R428US', $loggedUser)
|
||||
->first();
|
||||
|
||||
if (!$user) {
|
||||
return $defaults;
|
||||
}
|
||||
|
||||
return [
|
||||
'UserCO' => trim((string) ($user->R428CO ?? '')),
|
||||
'UserWHS' => trim((string) ($user->R428WH ?? '')),
|
||||
'UserPL' => trim((string) ($user->R428PL ?? '')),
|
||||
];
|
||||
} catch (\Throwable $e) {
|
||||
\Illuminate\Support\Facades\Log::warning('M3 user context unavailable', ['exception' => $e->getMessage()]);
|
||||
return $defaults;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
if (! function_exists('m3_user')) {
|
||||
/**
|
||||
* Return the current Core username in the format expected by the legacy M3 data.
|
||||
* M3 previously depended on PHP Basic Auth and read PHP_AUTH_USER directly.
|
||||
*/
|
||||
function m3_user(): string
|
||||
{
|
||||
$user = auth()->user();
|
||||
|
||||
$value = $user?->username
|
||||
?? $user?->user_name
|
||||
?? $user?->name
|
||||
?? $user?->email
|
||||
?? request()->server('PHP_AUTH_USER')
|
||||
?? '';
|
||||
|
||||
if (str_contains((string) $value, '@')) {
|
||||
$value = strstr((string) $value, '@', true) ?: $value;
|
||||
}
|
||||
|
||||
return strtoupper(trim((string) $value));
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('m3_legacy_password')) {
|
||||
/**
|
||||
* Passwords are intentionally unavailable in Core. PostgreSQL access uses
|
||||
* Laravel's configured connection and never reuses a user's login password.
|
||||
*/
|
||||
function m3_legacy_password(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
if (! function_exists('subdirAsset')) {
|
||||
function subdirAsset($path){
|
||||
return asset( (App::environment('production') ? env('APP_DIR') : '')."/".$path);
|
||||
}
|
||||
}
|
||||
if (! function_exists('subdirMix')) {
|
||||
function subdirMix($path){
|
||||
return mix( (App::environment('production') ? env('APP_DIR') : '')."/".$path);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
// app/Helpers/USStates.php
|
||||
|
||||
namespace Modules\M3\Helpers;
|
||||
|
||||
class USStates
|
||||
{
|
||||
public static function all()
|
||||
{
|
||||
return [
|
||||
'AL' => 'Alabama',
|
||||
'AK' => 'Alaska',
|
||||
'AZ' => 'Arizona',
|
||||
'AR' => 'Arkansas',
|
||||
'CA' => 'California',
|
||||
'CO' => 'Colorado',
|
||||
'CT' => 'Connecticut',
|
||||
'DE' => 'Delaware',
|
||||
'FL' => 'Florida',
|
||||
'GA' => 'Georgia',
|
||||
'HI' => 'Hawaii',
|
||||
'ID' => 'Idaho',
|
||||
'IL' => 'Illinois',
|
||||
'IN' => 'Indiana',
|
||||
'IA' => 'Iowa',
|
||||
'KS' => 'Kansas',
|
||||
'KY' => 'Kentucky',
|
||||
'LA' => 'Louisiana',
|
||||
'ME' => 'Maine',
|
||||
'MD' => 'Maryland',
|
||||
'MA' => 'Massachusetts',
|
||||
'MI' => 'Michigan',
|
||||
'MN' => 'Minnesota',
|
||||
'MS' => 'Mississippi',
|
||||
'MO' => 'Missouri',
|
||||
'MT' => 'Montana',
|
||||
'NE' => 'Nebraska',
|
||||
'NV' => 'Nevada',
|
||||
'NH' => 'New Hampshire',
|
||||
'NJ' => 'New Jersey',
|
||||
'NM' => 'New Mexico',
|
||||
'NY' => 'New York',
|
||||
'NC' => 'North Carolina',
|
||||
'ND' => 'North Dakota',
|
||||
'OH' => 'Ohio',
|
||||
'OK' => 'Oklahoma',
|
||||
'OR' => 'Oregon',
|
||||
'PA' => 'Pennsylvania',
|
||||
'RI' => 'Rhode Island',
|
||||
'SC' => 'South Carolina',
|
||||
'SD' => 'South Dakota',
|
||||
'TN' => 'Tennessee',
|
||||
'TX' => 'Texas',
|
||||
'UT' => 'Utah',
|
||||
'VT' => 'Vermont',
|
||||
'VA' => 'Virginia',
|
||||
'WA' => 'Washington',
|
||||
'WV' => 'West Virginia',
|
||||
'WI' => 'Wisconsin',
|
||||
'WY' => 'Wyoming',
|
||||
'DC' => 'District of Columbia'
|
||||
];
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,464 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers\API;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use DB;
|
||||
use Config;
|
||||
use Str;
|
||||
use Log;
|
||||
use Modules\M3\Helpers\Helper;
|
||||
|
||||
class M3Controller extends Controller
|
||||
{
|
||||
# Split Data and Write to ICM666M2
|
||||
public function insertToICM666M2($dataSplit, $commentData)
|
||||
{
|
||||
// dump($commentData);
|
||||
// dump($dataSplit);
|
||||
|
||||
$commentDataSS = explode("\n", $dataSplit);
|
||||
$AXLINENO = 1;
|
||||
foreach ($commentDataSS as $substring) {
|
||||
# Process each substring
|
||||
$fullData = $commentData;
|
||||
$fullData['AXCOMMENT'] = $substring;
|
||||
$fullData['AXLINENO'] = $AXLINENO;
|
||||
// dump($fullData);
|
||||
$insertSQL = DB::connection(config('m3.connection', 'pgsql'))->table('icm666m2')->insert($fullData);
|
||||
|
||||
$AXLINENO++;
|
||||
|
||||
# AXCO ICM666M2 CHARACTER 3
|
||||
# AXWHS ICM666M2 CHARACTER 3
|
||||
# AXPLANT ICM666M2 CHARACTER 3
|
||||
# AXDOCUMENT ICM666M2 CHARACTER 15
|
||||
# AXCOMMENT ICM666M2 CHARACTER 60
|
||||
# AXLINENO DECIMAL(3,0)
|
||||
}
|
||||
}
|
||||
|
||||
public function index(){ dd("Index"); }
|
||||
public function create(){}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('max_input_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOut'));
|
||||
|
||||
$REQKPKUS = m3_user() !== '' ? Str::upper(m3_user()) : 'WEBUSER';
|
||||
$SHSOURCE = 'M3ReceiverAPI';
|
||||
|
||||
$ICM666MFields = [
|
||||
'Company' =>[ 'A1CO' ,3 , 'string' ],
|
||||
'Warehouse' =>[ 'A1WHS', 3, 'string'],
|
||||
'Plant' =>[ 'A1PLANT', 3, 'string'],
|
||||
'PickerNumber' =>[ 'A1DELNO',11,'integer'],
|
||||
'OrderNumber' =>[ 'A1ONO' ,10, 'string'],
|
||||
'ReleaseNumber' =>[ 'A1RLNO' , 3,'string'], # Pick list suffix in ICM666M
|
||||
'ShipmentNumber' =>[ 'A1SHNO' ,7,'string'],
|
||||
'OrderLine' =>[ 'A1PKLN',6,'integer'],
|
||||
'PartNumber' =>[ 'A1PART', 15,'string'],
|
||||
'Description' =>[ 'A1PARTDES', 120,'string'],
|
||||
'Quantity' =>[ 'A1RSVQTY', 22,'DEC'],
|
||||
'BaseUnitPrice' =>[ 'A1SLUNPR', 22,'DEC'],
|
||||
'Currency' =>[ 'A1SHCURR',3,'string'],
|
||||
'Zone' =>[ 'A1LVZONE', 2,'string'],
|
||||
'PromDate' =>[ 'A1PROMDTE',8,'integer'],
|
||||
'RouteCode' =>[ 'A1SHSRT' ,6,'string'],
|
||||
'BillToId' =>[ 'A1BILLTO' ,10,'string'],
|
||||
'ShipToId' =>[ 'A1SHIPTO',10,'string'],
|
||||
'CompanyName' =>[ 'A1SHSHNM',36,'string'],
|
||||
'Address1' =>[ 'A1SHSHA1', 36,'string'],
|
||||
'Address2' =>[ 'A1SHSHA2', 36,'string'],
|
||||
'Address3' =>[ 'A1SHSHA3', 36,'string'],
|
||||
'Address4' =>[ 'A1SHSHA4', 36,'string'],
|
||||
'City' =>[ 'A1SHSHCI', 20,'string'],
|
||||
'State' =>[ 'A1SHSHST', 2,'string'],
|
||||
'PostalCode' =>[ 'A1SHSHZP', 10,'string'],
|
||||
'Country' =>[ 'A1SHSHCT',3,'string'],
|
||||
'CountryName' =>[ 'A1SHP2CNTY', 40,'string'],
|
||||
'PartWeight' =>[ 'A1PRTWGT', 15,'integer'],
|
||||
'SellUOM' =>[ 'A1SLUOM', 3,'string'],
|
||||
'PartConv' =>[ 'A1PARTCONV', 25,'DEC'],
|
||||
'CarrierCode' =>[ 'A1CARRIER', 6,'string'],
|
||||
'ShipVia' =>[ 'A1SHPVIA', 3,'string'],
|
||||
'PrimaryLocation' =>[ 'A1PRIMLOC', 10,'string'],
|
||||
'Allocation' =>[ 'A1SPR10A01', 10,'string'],
|
||||
'AllocatedTo' =>[ 'A1SPR15A01', 10,'string'],
|
||||
'LocationSeq' =>[ 'A1LOCSEQ', 10,'string'],
|
||||
'UOM' =>[ 'A1UOM' , 3,'string'],
|
||||
'HazMat' =>[ 'A1MATWRN', 4,'string'],
|
||||
'PartUPC' =>[ 'A1UPC', 30,'string'],
|
||||
'PartEAN' =>[ 'A1EAN', 30,'string'],
|
||||
'LotFlag' =>[ 'A1IZLCF', 1,'string'],
|
||||
'ManOrd' =>[ 'A1MONUM', 30,'string'],
|
||||
'LotNumber' =>[ 'A1LOTNUM', 30,'string'],
|
||||
'ProductArea' =>[ 'A1LVUSD1', 15,'string'],
|
||||
'FreightClass' =>[ 'A1WBFRCT' , 10,'string'],
|
||||
'ShipmentPONumber' =>[ 'A1SOPONO', 20,'string'],
|
||||
'ShipmentPOLine' =>[ 'A1SOPOLN' , 7,'integer'],
|
||||
'ShipTerms' =>[ 'A1OFSTRM', 3,'string'],
|
||||
// 'ExchangeRate' =>[ 'A1EXGRATE', 18,'DEC'],
|
||||
'OrderClass' =>[ 'A1SHORCL', 3,'string'],
|
||||
'LocationType' =>[ 'A1LVUSD2', 2,'string'],
|
||||
'PallSize' =>[ 'A1LVUSD3', 10,'string'],
|
||||
'MasterCarton' =>[ 'A1USRLD1', 30,'string'],
|
||||
'MasterQty' =>[ 'A1WBSHQY', 25,'DEC'],
|
||||
'InnerQty' =>[ 'A1WBPKQY', 25,'DEC'],
|
||||
'PalletQty' =>[ 'A1USRN01', 24,'DEC'],
|
||||
'CartonQty' =>[ 'A1USRN31', 25,'DEC'],
|
||||
'PersonName' =>[ 'A1PERNAME', 30,'string'],
|
||||
'AccountNo' =>[ 'A1ACCNUM', 20,'string'],
|
||||
'Email' =>[ 'A1EMAIL', 100,'string'],
|
||||
'OrderCategory' =>[ 'A1REFORD', 1,'string'],
|
||||
'A1DATEADD' =>[ 'A1DATEADD', 12,'string'],
|
||||
'A1TIMEADD' =>[ 'A1TIMEADD', 12,'string'],
|
||||
'KitPartNumber' =>[ 'A1KITPART', 15,'string'],
|
||||
'OrderLineSuffix' =>[ 'A1PKSFX', 6,'DEC'],
|
||||
'CustomerPartNumber'=>[ 'A1CUSTPART', 20,'string'],
|
||||
'GS1Label' => ['A1SPR1A01', 1, 'string'],
|
||||
'CurrencyExchangeRate' =>[ 'A1EXGRATE', 18,'DEC'],
|
||||
|
||||
];
|
||||
|
||||
try {
|
||||
$jsonFile = count($request->json()->all()) > 0 ? $request->json()->all() : '';
|
||||
|
||||
# Root
|
||||
$Company = isset($jsonFile["Company"]) ? $jsonFile["Company"] : '';
|
||||
$Plant = isset($jsonFile["Plant"]) ? $jsonFile["Plant"] : '';
|
||||
$Warehouse = isset($jsonFile["Warehouse"]) ? $jsonFile["Warehouse"] : '';
|
||||
$OrderNumber = isset($jsonFile["OrderNumber"]) ? $jsonFile["OrderNumber"] : '';
|
||||
$PickerNumber = isset($jsonFile["PickerNumber"]) ? $jsonFile["PickerNumber"] : '';
|
||||
$PromDate = isset($jsonFile["PromDate"]) ? $jsonFile["PromDate"] : '';
|
||||
$RouteCode = isset($jsonFile["RouteCode"]) ? $jsonFile["RouteCode"] : '';
|
||||
$OrderCategory = isset($jsonFile["OrderCategory"]) ? $jsonFile["OrderCategory"] : '';
|
||||
$ReleaseNumber = isset($jsonFile["ReleaseNumber"]) ? $jsonFile["ReleaseNumber"] : '';
|
||||
$ShipmentNumber = isset($jsonFile["ShipmentNumber"]) ? $jsonFile["ShipmentNumber"] : '';
|
||||
$Currency = isset($jsonFile["Currency"]) ? $jsonFile["Currency"] : '';
|
||||
$CarrierCode = isset($jsonFile["CarrierCode"]) ? $jsonFile["CarrierCode"] : '';
|
||||
$ShipmentPONumber = isset($jsonFile["ShipmentPONumber"]) ? $jsonFile["ShipmentPONumber"] : ''; // CustPo
|
||||
$ShipTerms = isset($jsonFile["ShipTerms"]) ? $jsonFile["ShipTerms"] : '';
|
||||
// $ExchangeRate = isset($jsonFile["ExchangeRate"]) ? $jsonFile["ExchangeRate"] : '';
|
||||
$OrderClass = isset($jsonFile["OrderClass"]) ? $jsonFile["OrderClass"] : '';
|
||||
$GS1Label = isset($jsonFile["GS1-128Label"]) ? $jsonFile["GS1-128Label"] : '0';
|
||||
$CurrencyExchangeRate = isset($jsonFile["CurrencyExchangeRate"]) ? $jsonFile["CurrencyExchangeRate"] : '';
|
||||
|
||||
# Set Carrier BWAY if it's empty for Tilburg only
|
||||
if (($CarrierCode=='' || $CarrierCode==null) && $Warehouse=='111' && $Company=='410' && $Plant=='410' ) {
|
||||
$CarrierCode = 'BWAY';
|
||||
}
|
||||
|
||||
$SHMACPKR = $PickerNumber!='' ? $PickerNumber : '000000';
|
||||
|
||||
if($jsonFile!=''){
|
||||
# Order Category
|
||||
/*
|
||||
1 = Material to manufacturing order
|
||||
3 = Customer Order
|
||||
4 = Requisition Order
|
||||
5 = Distribution Order
|
||||
9 = Move order / Replenishment
|
||||
*/
|
||||
|
||||
# Recipient
|
||||
$recipient = $jsonFile["Recipient"];
|
||||
$CompanyName = isset($recipient["CompanyName"]) ? $recipient["CompanyName"] : '';
|
||||
$Address1 = isset($recipient["Address1"]) ? $recipient["Address1"]: '';
|
||||
$Address2 = isset($recipient["Address2"]) ? $recipient["Address2"] : '';
|
||||
$City = isset($recipient["City"]) ? $recipient["City"] : '';
|
||||
$State = isset($recipient["State"]) ? $recipient["State"] : '';
|
||||
$PostalCode = isset($recipient["PostalCode"]) ? $recipient["PostalCode"]: '';
|
||||
$Country = isset($recipient["Country"]) ? $recipient["Country"]: '';
|
||||
$PostalCode = isset($recipient["PostalCode"]) ? $recipient["PostalCode"]: '';
|
||||
$BillToId = isset($recipient["BillToId"]) ? $recipient["BillToId"]: '';
|
||||
$ShipToId = isset($recipient["ShipToId"]) ? $recipient["ShipToId"]: '';
|
||||
$Address3 = isset($recipient["Address3"]) ? $recipient["Address3"] : '';
|
||||
$Address4 = isset($recipient["Address4"]) ? $recipient["Address4"] : '';
|
||||
$CountryName = isset($recipient["CountryName"]) ? $recipient["CountryName"] : '';
|
||||
$PersonName = isset($recipient["PersonName"]) ? $recipient["PersonName"] : '';
|
||||
$AccountNo = isset($recipient["AccountNo"]) ? $recipient["AccountNo"] : '';
|
||||
$Email = isset($recipient["Email"]) ? $recipient["Email"] : '';
|
||||
$A1DATEADD = date("Ymd");
|
||||
$A1TIMEADD = date("His");
|
||||
|
||||
# MycarrierDetails
|
||||
$ShipVia = isset($jsonFile["ShipVia"]) ? $jsonFile["ShipVia"]: '';
|
||||
|
||||
# Comments
|
||||
$Picker = $Packer = $Carrier = $Other ='';
|
||||
$AXCO = $Company;
|
||||
$AXPLANT = $Plant;
|
||||
$AXWHS = $Warehouse;
|
||||
$AXDELNO = $PickerNumber;
|
||||
$AXONO = $OrderNumber;
|
||||
$AXRLNO = $ReleaseNumber;
|
||||
$AXSHNO = $ShipmentNumber;
|
||||
|
||||
$comments = isset($jsonFile["Comments"]) ? $jsonFile["Comments"] : '';
|
||||
|
||||
if ($comments!='') {
|
||||
foreach($comments as $key => $comment) {
|
||||
$commentData = [];
|
||||
$AXDOCUMENT = Helper::sanityzeString($key);
|
||||
|
||||
$commentData=["AXCO"=>$AXCO,"AXPLANT"=>$AXPLANT,"AXWHS"=>$AXWHS,"AXDELNO"=>$AXDELNO,"AXONO"=>$AXONO,
|
||||
"AXRLNO"=>$AXRLNO,"AXSHNO"=>$AXSHNO,"AXDOCUMENT"=>$AXDOCUMENT];
|
||||
// dump($commentData);
|
||||
|
||||
switch ($AXDOCUMENT) {
|
||||
case 'Picker':
|
||||
$Picker = isset($comment) ? Helper::sanityzeString($comment) : 'null';
|
||||
// dump($Picker);
|
||||
if ($Picker!='null') {
|
||||
$this->insertToICM666M2($Picker,$commentData);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Packer':
|
||||
$Packer = isset($comment) ? Helper::sanityzeString($comment) : 'null';
|
||||
// dump($Packer);
|
||||
if ($Packer!='null') {
|
||||
$this->insertToICM666M2($Packer,$commentData);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Carrier':
|
||||
$Carrier = isset($comment) ? Helper::sanityzeString($comment) : 'null';
|
||||
// dump($Carrier);
|
||||
if ($Carrier!='null') {
|
||||
$this->insertToICM666M2($Carrier,$commentData);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Other':
|
||||
$Other = isset($comment) ? Helper::sanityzeString($comment) : 'null';
|
||||
// dump($Other);
|
||||
if ($Other!='null') {
|
||||
$this->insertToICM666M2($Other,$commentData);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Get Products : commodities And Write ICM666M
|
||||
$tmpProd = "";
|
||||
$products = $jsonFile["Contents"]["Commodities"];
|
||||
foreach($products as $key => $product) {
|
||||
$Quantity = isset($product['Quantity']) ? $product['Quantity'] : '';
|
||||
$Description = isset($product['Description']) ? Str::limit($product['Description'],25,'') : '';
|
||||
$PartNumber = isset($product['PartNumber']) ? $product['PartNumber']: '';
|
||||
$OrderLine = isset($product['OrderLine']) ? $product['OrderLine']: '';
|
||||
$PartWeight = isset($product['PartWeight']) ? $product['PartWeight']: '';
|
||||
$PickerLine = isset($product['PickerLine']) ? $product['PickerLine']: '';
|
||||
$PrimaryLocation = isset($product['PrimaryLocation']) ? $product['PrimaryLocation']: '';
|
||||
$Allocation = isset($product['Allocation']) ? $product['Allocation']: '';
|
||||
$AllocatedTo = isset($product['AllocatedTo']) ? $product['AllocatedTo']: '';
|
||||
$LocationSeq = isset($product['LocationSeq']) ? $product['LocationSeq']: '';
|
||||
$Zone = isset($product['Zone']) ? $product['Zone']: '';
|
||||
$BaseUnitPrice = isset($product['BaseUnitPrice']) ? $product['BaseUnitPrice'] : '';
|
||||
$FrgnUnitPrice = isset($product['FrgnUnitPrice']) ? $product['FrgnUnitPrice'] : '';
|
||||
$SellUOM = isset($product['SellUOM']) ? $product['SellUOM'] : '';
|
||||
$PartConv = isset($product['PartConv']) ? $product['PartConv'] : '';
|
||||
$UOM = isset($product['UOM']) ? $product['UOM']: '';
|
||||
$HazMat = isset($product['HazMat']) ? $product['HazMat']: '';
|
||||
$PartUPC = isset($product['PartUPC']) ? $product['PartUPC']: '';
|
||||
$PartEAN = isset($product['PartEAN']) ? $product['PartEAN']: '';
|
||||
$LotFlag = isset($product['LotFlag']) ? $product['LotFlag']: '';
|
||||
$ManOrd = isset($product['ManOrd']) ? $product['ManOrd']: '';
|
||||
$LotNumber = isset($product['LotNumber']) ? $product['LotNumber']: '';
|
||||
$ProductArea = isset($product['ProductArea']) ? $product['ProductArea']: '';
|
||||
$FreightClass = isset($product['FreightClass']) ? $product['FreightClass']: '';
|
||||
$ShipmentPOLine = isset($product['ShipmentPOLine']) ? $product['ShipmentPOLine']: '';
|
||||
$LocationType = isset($product['LocationType']) ? $product['LocationType']: '';
|
||||
$PallSize = isset($product['PallSize']) ? $product['PallSize']: '';
|
||||
$MasterCarton = isset($product['MasterCarton']) ? $product['MasterCarton']: '';
|
||||
$MasterQty = isset($product['MasterQty']) ? $product['MasterQty']: '';
|
||||
$InnerQty = isset($product['InnerQty']) ? $product['InnerQty']: '';
|
||||
$PalletQty = isset($product['PalletQty']) ? $product['PalletQty']: '';
|
||||
$CartonQty = isset($product['CartonQty']) ? $product['CartonQty']: '';
|
||||
$KitPartNumber = isset($product['KitPartNumber']) ? $product['KitPartNumber']: '';
|
||||
$OrderLineSuffix = isset($product['OrderLineSuffix']) ? $product['OrderLineSuffix']: '';
|
||||
$CustomerPartNumber = isset($product['CustomerPartNumber']) ? substr($product['CustomerPartNumber'], 0, 20): ''; # Limit to 20 Chars
|
||||
|
||||
# Initialise Table Fields to be filled
|
||||
$InsertArray = [];
|
||||
|
||||
# Check JSON fields if empty or > DB Fields
|
||||
foreach ($ICM666MFields as $key => $value) {
|
||||
$keyVar = $key;
|
||||
# Sanitize String
|
||||
$$keyVar = Helper::sanityzeString($$keyVar);
|
||||
# Check Var Types & Length
|
||||
$LengthTest = Helper::checkLength($$keyVar, $value[1], $value[2]);
|
||||
|
||||
if (!$LengthTest[413] || !$LengthTest[411] || !$LengthTest[417]) {
|
||||
// Log::error($key .' :: '. $value[0].' :: '. $value[1] .' JSONF: '.$$keyVar .' Type: '.$value[2] );
|
||||
if(!$LengthTest[413]){
|
||||
$message[] = [ 'code'=>'413', 'status'=>'error', 'message'=>'Field: '.$key.' is larger then expected'];
|
||||
}
|
||||
if(!$LengthTest[411]){
|
||||
$message[] = [ 'code'=>'411', 'status'=>'error', 'message'=>'Field: '.$key.' is empty'];
|
||||
}
|
||||
if(!$LengthTest[417]){
|
||||
$message[] = [ 'code'=>'417', 'status'=>'error', 'message'=>'Field: '.$key.'type is different then Expected type: '.$value[2]];
|
||||
}
|
||||
|
||||
# Write to Logs Out : Error & JSON
|
||||
$data = ['SHMACPKR'=>$SHMACPKR,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> 'X','SHINTBOX'=> '','SHTYPE'=> 'M3-Lis-spl' ,
|
||||
'SHDATA'=> json_encode($message).' M3-Lis-JSN'.json_encode($jsonFile) ,'SHUSER'=> $REQKPKUS,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$Company,'SHWHS'=>$Warehouse ];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
return response()->json($message);
|
||||
} else if ($$keyVar != '') {
|
||||
$InsertArray[$value[0]] = $$keyVar;
|
||||
}
|
||||
}
|
||||
// Log::info($InsertArray);
|
||||
|
||||
# Check ICM709M
|
||||
$ICM709MSEL = DB::connection(config('m3.connection', 'pgsql'))->table('icm709m')
|
||||
->select()
|
||||
->where('AT9CO',$AXCO)
|
||||
->where('AT9PLT',$AXPLANT)
|
||||
->where('AT9WHS',$AXWHS)
|
||||
->where('AT9PART',$PartNumber)
|
||||
->first();
|
||||
$palletQty = isset($ICM709MSEL->AT9QTY) ? $ICM709MSEL->AT9QTY : 0;
|
||||
// dd($palletQty);
|
||||
# Get Pallet Qty
|
||||
$InsertArray['A1USRN01'] = $palletQty;
|
||||
|
||||
# Hazard Material
|
||||
$HazMat = isset($ICM709MSEL->AT9WRN) ? $ICM709MSEL->AT9WRN : '';
|
||||
$InsertArray['A1MATWRN'] = $HazMat;
|
||||
|
||||
// if ($PalletQty!='') {
|
||||
// $InsertArray['A1USRN01']=$palletQty;
|
||||
// }
|
||||
|
||||
# SQL Insert to ICM666M
|
||||
$insertSQL = DB::connection(config('m3.connection', 'pgsql'))->table('icm666m')->insert($InsertArray);
|
||||
}
|
||||
|
||||
# Call PGM ICM700CSBM
|
||||
if ($Warehouse!='' && $PickerNumber!='' && $Company!='') {
|
||||
$PGMERRORS = '';
|
||||
$AWREQN = '';
|
||||
|
||||
# connect to toolkit using DB2 credentials (can also leave blank for default authority)
|
||||
try {
|
||||
$conn = app(\Modules\M3\Services\PostgresProgramBridge::class);
|
||||
} catch (Exception $e) {
|
||||
# Determine reason for failure.
|
||||
# Probably database authentication error or invalid or unreachable database.
|
||||
$code = $e->getCode();
|
||||
$msg = $e->getMessage();
|
||||
|
||||
switch ($code) {
|
||||
case 8001:
|
||||
# "Authorization failure on distributed database connection attempt"
|
||||
# Usually means a wrong DB2 user or password
|
||||
$PGMERRORS = 'Could not connect due to wrong user or password.';
|
||||
break;
|
||||
case 42705:
|
||||
$PGMERRORS = 'Database not found. Try WRKRDBDIRE to check.';
|
||||
break;
|
||||
default:
|
||||
$PGMERRORS = 'Could not connect. Error: ' . $code . ' ' . $msg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$conn->setOptions(array('persistent' => false, 'stateless' => true, 'debug' => true,'debugLogFile' => env('TOOLKIT_DEBUG_LOG')));
|
||||
|
||||
# Add LIB
|
||||
# $result = $conn->CLCommand('ADDLIBLE LIB(MPDAT10)');
|
||||
|
||||
# define several input/output params
|
||||
$params = [];
|
||||
# $params[] = $conn->AddParameterChar('out',7,'eqNumber');
|
||||
|
||||
# AddParameterChar($io, $size, $comment, $varName, $value, $varying, $dimension)
|
||||
# Add Warehouse Param
|
||||
$params[] = $conn->AddParameterChar('in',3,'Company','',$Company);
|
||||
|
||||
$params[] = $conn->AddParameterChar('in',3,'Warehouse','',$Warehouse);
|
||||
|
||||
# AddParameterPackDec($io, $length, $scale, $comment, $varName, $value,$dimension)
|
||||
# Add Delivery Note Param
|
||||
$PickerNumberNoZero = ltrim(strval($PickerNumber), '0');
|
||||
$params[] = $conn->AddParameterChar('in', 11, 'PickerNumber','',$PickerNumberNoZero);
|
||||
// $params[] = $conn->AddParameterZoned('in', 11, 0, 'ParamIn');
|
||||
|
||||
# Start Time Tracking
|
||||
$start = microtime(true);
|
||||
|
||||
# ICM700C EWOBJTST ICM700C ICM700CSBM
|
||||
$result = $conn->PgmCall('ICM700CSBM', env('OBJLIB'), $params, array(), array());
|
||||
|
||||
if (!$result) {
|
||||
$PGMERRORS = 'Error calling program. Code: ' . $conn->getErrorCode() . ' - Msg: ' . $conn->getErrorMsg();
|
||||
}
|
||||
|
||||
if ($PGMERRORS != '') {
|
||||
# Write to Logs Out : Error & JSON
|
||||
$data = ['SHMACPKR'=>$SHMACPKR,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> 'X','SHINTBOX'=> '','SHTYPE'=> 'M3-Lis-spl' ,
|
||||
'SHDATA'=>$PGMERRORS .' M3-Lis-JSN'.json_encode($jsonFile) ,'SHUSER'=> $REQKPKUS,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$Company,'SHWHS'=>$Warehouse ];
|
||||
Helper::logToICM699M($data);
|
||||
}
|
||||
}
|
||||
|
||||
# Write to Logs Out : Success
|
||||
$data = ['SHMACPKR'=>$SHMACPKR,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> '','SHINTBOX'=> '','SHTYPE'=> 'M3-Lis-in' ,
|
||||
'SHDATA'=>json_encode($jsonFile) ,'SHUSER'=> $REQKPKUS,'SHSOURCE'=> $SHSOURCE ,'SHCO'=>$Company,'SHWHS'=>$Warehouse];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
return response()->json([
|
||||
'code'=>'200',
|
||||
'status'=>'success',
|
||||
'message'=>'File Received, DB Updated'
|
||||
]);
|
||||
}
|
||||
else{
|
||||
# Write to Logs Out : Error & JSON
|
||||
$SHACKNOTE = 'Sentinel automatically closed the error related to this empty data set sent by M3';
|
||||
|
||||
$data = ['SHMACPKR'=>$SHMACPKR,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> 'Z','SHINTBOX'=> '','SHTYPE'=> 'M3-Lis-in' ,
|
||||
'SHDATA'=>'No Json File Found...' ,'SHUSER'=> $REQKPKUS,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$Company,'SHWHS'=>$Warehouse,"SHACKNOTE"=> $SHACKNOTE ];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
return response()->json([
|
||||
'code'=>'415',
|
||||
'status'=>'error',
|
||||
'message'=>'No Json File Found'
|
||||
]);
|
||||
}
|
||||
}
|
||||
catch (\Throwable $th) {
|
||||
# Write to Logs Out : Error & JSON
|
||||
$data = ['SHMACPKR'=>$SHMACPKR,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> 'X','SHINTBOX'=> '','SHTYPE'=> 'M3-Lis-in' ,
|
||||
'SHDATA'=>'General Catchable Error - '.substr($th,0,300).' M3-Lis-JSN'.json_encode($jsonFile) ,'SHUSER'=> $REQKPKUS,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$Company,'SHWHS'=>$Warehouse ];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
// Log::error($th);
|
||||
return response()->json([
|
||||
'code'=>'405',
|
||||
'status'=>'error',
|
||||
'message'=>'An Error Occured...'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function show($id){}
|
||||
|
||||
public function edit($id){}
|
||||
|
||||
public function update(Request $request, $id){}
|
||||
|
||||
public function destroy($id){}
|
||||
}
|
||||
@@ -0,0 +1,453 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers\API;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use DB;
|
||||
use Config;
|
||||
use Str;
|
||||
use Log;
|
||||
use Http;
|
||||
use Cache;
|
||||
use DateTime;
|
||||
use Smalot\PdfParser\Parser;
|
||||
use File;
|
||||
use Modules\M3\Helpers\Helper;
|
||||
use Json;
|
||||
|
||||
class M3InventoryReport extends Controller
|
||||
{
|
||||
# M3InventoryReport for Single Part
|
||||
public function M3InventoryReport(Request $request){
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('max_input_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOut'));
|
||||
// dd($request->json()->all());
|
||||
|
||||
# Get the Calling User
|
||||
$SHUSER = m3_user() !== '' ? Str::upper(m3_user()) : 'WEBUSER';
|
||||
# Set SHSOURCE
|
||||
$SHSOURCE = 'M3InventoryReport';
|
||||
$M3Errors = '';
|
||||
$DELIVERYNO = isset($DELIVERYNO) ? $DELIVERYNO : '000000';
|
||||
|
||||
try {
|
||||
# Get Json Contents
|
||||
$jsonFile = count($request->json()->all())>0 ? $request->json()->all() : '';
|
||||
if($jsonFile!=''){
|
||||
$WHS = isset($jsonFile["WHS"]) ? $jsonFile["WHS"] : '';
|
||||
$PART = isset($jsonFile["PART"]) ? $jsonFile["PART"] : '';
|
||||
$LOT = isset($jsonFile["LOT"]) ? $jsonFile["LOT"] : '';
|
||||
}
|
||||
else {
|
||||
# code...
|
||||
}
|
||||
|
||||
# Get Token
|
||||
$tokenResponse = Helper::checkReceiveTokenV2();
|
||||
$tokenData = $tokenResponse->getData();
|
||||
if($tokenData->code=='200'){
|
||||
$IonToken = isset($tokenData->token) ? $tokenData->token : '';
|
||||
}
|
||||
else{
|
||||
$SHDATA = isset($tokenData->message) ? $tokenData->message : '';
|
||||
# Write to Logs : Error
|
||||
$data = ['SHMACPKR'=>'000000','SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> '','SHINTBOX'=> '','SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=> $SHDATA ,'SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,'SHCO'=>'','SHWHS'=>$WHS];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
return $tokenResponse;
|
||||
}
|
||||
|
||||
# Call ionapi with Params
|
||||
$endPointURL = env('ENDPOINTURL').'APIFLOWS/Sentinel/M3InventoryReport?ionapiRespStyle=sync';
|
||||
$token = $IonToken;
|
||||
$JSON = [
|
||||
"WHS" => $WHS,
|
||||
"PART"=> $PART,
|
||||
"LOT" => $LOT
|
||||
];
|
||||
|
||||
$response = Http::withHeaders([
|
||||
'accept' => 'application/json',
|
||||
'Content-Type' => 'application/json'
|
||||
])
|
||||
->withToken($token)
|
||||
->timeout(Config::get('arrays.curlTimeOut'))
|
||||
->post($endPointURL, $JSON);
|
||||
$responseStatusCode = $response->getStatusCode();
|
||||
|
||||
$M3SessionId = $response->hasHeader('x-transaction-id') ? "-sessionID:". $response->header('x-transaction-id') : '-sessionID';
|
||||
|
||||
if ($responseStatusCode =='200') {
|
||||
# Check M3 Response for Errors
|
||||
$M3Errors = '';
|
||||
$responseJSON = $response->getBody()->getContents();
|
||||
$JsonSanytized = Helper::sanityzeString($responseJSON);
|
||||
}
|
||||
else{
|
||||
$M3Errors = 'Error: No Response from M3';
|
||||
}
|
||||
|
||||
if ($M3Errors!='') {
|
||||
# Write to Logs : Error
|
||||
$data = ['SHMACPKR'=>$DELIVERYNO,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> 'X','SHINTBOX'=> '','SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=>$responseStatusCode.$M3Errors.$M3SessionId ,'SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,'SHCO'=>'','SHWHS'=>$WHS ];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
# Send Response
|
||||
return response()->json([
|
||||
'code'=>'405',
|
||||
'status'=>'error',
|
||||
'message'=>$M3Errors
|
||||
]);
|
||||
}
|
||||
else{
|
||||
# Write to Logs Out : Success
|
||||
$data = ['SHMACPKR'=>$DELIVERYNO,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> '','SHINTBOX'=> '','SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=>$responseStatusCode.$JsonSanytized.'-'.json_encode($JSON).$M3SessionId ,'SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,
|
||||
'SHCO'=>'','SHWHS'=>$WHS];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
return response()->json([
|
||||
'code'=>$responseStatusCode,
|
||||
'status'=>'Success',
|
||||
'message'=>json_decode($JsonSanytized)
|
||||
]);
|
||||
}
|
||||
}
|
||||
catch (\Throwable $th) {
|
||||
// Log::error($th);
|
||||
$getCurlErrors = str_contains($th->getMessage(), 'cURL error');
|
||||
if($getCurlErrors){
|
||||
# Write to Logs Out : Failed
|
||||
$data = ['SHMACPKR'=>$DELIVERYNO,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> 'X','SHINTBOX'=> '','SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=>'Curl Error: Communication with M3 Timed Out'.' M3-JSN-out'.$JSON ,'SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,'SHCO'=>'','SHWHS'=>$WHS];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
return response()->json([
|
||||
'code'=>'405',
|
||||
'status'=>'error',
|
||||
'message'=>'Curl Error: Communication with M3 Timed Out.'
|
||||
]);
|
||||
}
|
||||
else {
|
||||
# Write to Logs Out : Error
|
||||
$data = ['SHMACPKR'=>$DELIVERYNO,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> 'X','SHINTBOX'=> '','SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=>'An Error Occured - '.substr($th,0,300) ,'SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
return response()->json([
|
||||
'code'=>'405',
|
||||
'status'=>'error',
|
||||
'message'=>'Catched Error: '.$th
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
# End M3InventoryReport
|
||||
|
||||
# M3InventoryReportList with URL Params
|
||||
public function M3InventoryReportListURL(Request $request){
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('max_input_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOut'));
|
||||
|
||||
# Set API Name
|
||||
$SHSOURCE = 'M3InventoryReportListURL';
|
||||
# Get The Calling User
|
||||
$SHUSER = m3_user() !== '' ? Str::upper(m3_user()) : 'WebUser';
|
||||
$M3Errors = '';
|
||||
|
||||
try {
|
||||
# Get Json Contents
|
||||
$urlParams = count($request->all())>0 ? $request->all() : '';
|
||||
|
||||
$REQPKWS = isset($urlParams["REQPKWS"]) ? $urlParams["REQPKWS"] : '';
|
||||
$REQKPKUS = isset($urlParams["REQKPKUS"]) ? $urlParams["REQKPKUS"] : 'WebUser';
|
||||
$CO = isset($urlParams["CO"]) ? $urlParams["CO"] : '';
|
||||
$WHS = isset($urlParams["WHS"]) ? $urlParams["WHS"] : '';
|
||||
$MACPKR = isset($urlParams["MACPKR"]) ? $urlParams["MACPKR"] : '000000'; # Delivery Number
|
||||
$PKLN = isset($urlParams["PKLN"]) ? $urlParams["PKLN"] : '';
|
||||
|
||||
if($urlParams!=''){
|
||||
$IncomingParams = ['CO'=> $CO,'WHS'=> $WHS,'MACPKR'=> $MACPKR,'PKLN'=> $PKLN,'REQPKWS'=> $REQPKWS,'REQKPKUS'=> $REQKPKUS];
|
||||
$IncomingParams = json_encode($IncomingParams);
|
||||
|
||||
# Write to Logs : Params In
|
||||
$data = ['SHMACPKR'=>$MACPKR,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> '','SHINTBOX'=> '','SHTYPE'=> 'M3-Req-out' ,
|
||||
'SHDATA'=>$IncomingParams ,'SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$CO,'SHWHS'=>$WHS ];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
# Get Parts And Lots from ICM688M2
|
||||
$ICM688M2SLTMP = DB::connection(config('m3.connection', 'pgsql'))->table('icm688m2')
|
||||
->select('A5WHS', 'A5PART','A5LOTNUM','A5SENTPKR')
|
||||
->distinct()
|
||||
->where('A5CO',$CO)
|
||||
->where('A5WHS',$WHS)
|
||||
->where('A5MACPKR',$MACPKR);
|
||||
|
||||
# Get Pack Lines
|
||||
if($PKLN!=''){
|
||||
$ICM688M2SLTMP->where('A5PKLN',$PKLN);
|
||||
}
|
||||
$ICM688M2SL = $ICM688M2SLTMP->get();
|
||||
// dd($ICM688M2SL);
|
||||
|
||||
if( count($ICM688M2SL)>0 ){
|
||||
# Update ICM688M1 : Add Timestamp
|
||||
$ICM688M1TS = now();
|
||||
DB::connection(config('m3.connection', 'pgsql'))->table('icm688m1')
|
||||
->where('A4MACPKR',$MACPKR)
|
||||
->update(['A4INRFSHTS'=>$ICM688M1TS]);
|
||||
|
||||
$PICKERARR = [];
|
||||
foreach ($ICM688M2SL as $key => $ICM688M2) {
|
||||
$PART = trim($ICM688M2->A5PART);
|
||||
$LOT = trim($ICM688M2->A5LOTNUM);
|
||||
$PARTS[] = ["PART"=> $PART , "LOT"=>$LOT];
|
||||
$PICKERARR[$PART] = $ICM688M2->A5SENTPKR;
|
||||
}
|
||||
// Log::info($PARTS);
|
||||
// dump($PARTS);
|
||||
$JSON = json_encode( ["WHS" => $WHS,"PARTS"=> $PARTS ] );
|
||||
// Log::info($JSON);
|
||||
|
||||
# Get Token
|
||||
$tokenResponse = Helper::checkReceiveTokenV2();
|
||||
$tokenData = $tokenResponse->getData();
|
||||
if($tokenData->code=='200'){
|
||||
$IonToken = isset($tokenData->token) ? $tokenData->token : '';
|
||||
}
|
||||
else{
|
||||
$SHDATA = isset($tokenData->message) ? $tokenData->message : '';
|
||||
# Write to Logs : Error
|
||||
$data = ['SHMACPKR'=>$MACPKR,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> 'X','SHINTBOX'=> '','SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=> $SHDATA ,'SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$CO,'SHWHS'=>$WHS ];
|
||||
Helper::logToICM699M($data);
|
||||
return $tokenResponse;
|
||||
}
|
||||
|
||||
# Call ionapi with Params
|
||||
$endPointURL = env('ENDPOINTURL').'APIFLOWS/Sentinel/M3InventoryReportList?ionapiRespStyle=sync';
|
||||
$token = $IonToken;
|
||||
|
||||
$response = Http::withHeaders([
|
||||
'accept' => 'application/json',
|
||||
'Content-Type' => 'application/json'
|
||||
])
|
||||
->withToken($token)
|
||||
->withBody($JSON, 'application/json')
|
||||
->timeout(Config::get('arrays.curlTimeOut'))
|
||||
->post($endPointURL);
|
||||
|
||||
$M3SessionId = $response->hasHeader('x-transaction-id') ? "-sessionID:". $response->header('x-transaction-id') : '-sessionID';
|
||||
|
||||
$responseStatusCode = $response->getStatusCode();
|
||||
if ($responseStatusCode =='200') {
|
||||
# Check M3 Response for Errors
|
||||
$M3Errors = '';
|
||||
$responseJSON = $response->getBody()->getContents();
|
||||
$JsonSanytized = Helper::sanityzeString($responseJSON);
|
||||
# Array
|
||||
$responseArray = json_decode($JsonSanytized,true);
|
||||
$responseTMP = $responseArray['result'];
|
||||
}
|
||||
else{
|
||||
$M3Errors = 'Error: No Response from M3';
|
||||
}
|
||||
|
||||
# Validate response From M3
|
||||
if ($M3Errors!='') {
|
||||
# Write to Logs : Error
|
||||
$data = ['SHMACPKR'=>$MACPKR,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> 'X','SHINTBOX'=> '','SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=>$responseStatusCode.'-'.$M3Errors.$M3SessionId ,'SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$CO,'SHWHS'=>$WHS ];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
# Send Response
|
||||
return response()->json([
|
||||
'code'=>'405',
|
||||
'status'=>'error',
|
||||
'message'=>'Error: No Response from M3'
|
||||
]);
|
||||
}
|
||||
else{
|
||||
# Write to Logs : JSON
|
||||
$data = ['SHMACPKR'=>$MACPKR,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> '','SHINTBOX'=> '','SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=>$responseStatusCode.'-'.$JsonSanytized.$M3SessionId ,'SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$CO,'SHWHS'=>$WHS ];
|
||||
Helper::logToICM699M($data);
|
||||
}
|
||||
|
||||
$dataToWrite2 = [];
|
||||
foreach ($responseTMP as $key => $value) {
|
||||
// dump($value);
|
||||
$dataToWrite = [];
|
||||
|
||||
foreach ($value as $key2 => $content) {
|
||||
if($key2!='Locations'){
|
||||
$dataToWrite[$key2] = $content;
|
||||
}
|
||||
else{
|
||||
foreach ($content as $key3 => $content2) {
|
||||
//dump($content2);
|
||||
$dataToWrite2[] = array_merge($dataToWrite,$content2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// LOG::info($dataToWrite2);
|
||||
|
||||
# Delete Old Records from IC630M
|
||||
foreach ($dataToWrite2 as $key => $value) {
|
||||
$ICM630MDeleteSQL = DB::connection(config('m3.connection', 'pgsql'))->table('ic630m')
|
||||
->where('LLCO',$CO)
|
||||
->where('LLWHNO',$WHS)
|
||||
->where('LLPPN',trim($value['PartNumber']))
|
||||
->delete();
|
||||
}
|
||||
|
||||
foreach ($dataToWrite2 as $key => $value) {
|
||||
# Check if Location exist in DE640M ("LVCO", "WSELOC", "VLOCID")
|
||||
$DE640MSQLSEL = DB::connection(config('m3.connection', 'pgsql'))->table('de640m')
|
||||
->where('LVCO',$CO)
|
||||
->where('WSELOC',$value['Warehouse'])
|
||||
->where('VLOCID',$value['Location'])
|
||||
->first();
|
||||
// dd($DE640MSQLSEL);
|
||||
|
||||
$LocationExist = isset($DE640MSQLSEL->VLOCID) ? trim($DE640MSQLSEL->VLOCID) : '';
|
||||
$WHExist = isset($DE640MSQLSEL->WSELOC) ? trim($DE640MSQLSEL->WSELOC) : '';
|
||||
$COExist = isset($DE640MSQLSEL->LVCO) ? trim($DE640MSQLSEL->LVCO) : '';
|
||||
// dd($LocationExist .': '.$WHExist.': '.$COExist);
|
||||
|
||||
# if No records Founds insert New Record
|
||||
if ( $LocationExist=='' && $WHExist=='' && $COExist=='' ) {
|
||||
$SQLInsertPrep640M['LVCO'] = $CO; # Company
|
||||
$SQLInsertPrep640M['WSELOC'] = $value['Warehouse'];
|
||||
// $SQLInsertPrep640M['LVDELNO'] = $MACPKR; # M3 Delivery note number DELETED
|
||||
// $SQLInsertPrep640M['LVUSD3'] = $value['']; # Pallet Size : Not Found in M3 JSON
|
||||
$SQLInsertPrep640M['VLOCID'] = $value['Location']; # Stock location
|
||||
$SQLInsertPrep640M['LVSEQN'] = $value['LocationSeq'];
|
||||
$SQLInsertPrep640M['LVUSD2'] = $value['LocationType'];
|
||||
$SQLInsertPrep640M['LVZONE'] = $value['Zone']; # Warehouse zone
|
||||
$SQLInsertPrep640M['LVMAINTTS'] = now(); # Last maintained time stamp
|
||||
|
||||
DB::connection(config('m3.connection', 'pgsql'))->table('de640m')->insert($SQLInsertPrep640M);
|
||||
}
|
||||
# Update
|
||||
else {
|
||||
$SQLUpdatePrep640M['LVSEQN'] = $value['LocationSeq'];
|
||||
$SQLUpdatePrep640M['LVUSD2'] = $value['LocationType'];
|
||||
$SQLUpdatePrep640M['LVZONE'] = $value['Zone'];
|
||||
$SQLUpdatePrep640M['LVMAINTTS'] = now();
|
||||
|
||||
DB::connection(config('m3.connection', 'pgsql'))->table('de640m')
|
||||
->where('LVCO',$CO)
|
||||
->where('WSELOC',$value['Warehouse'])
|
||||
->where('VLOCID',$value['Location'])
|
||||
->update($SQLUpdatePrep640M);
|
||||
}
|
||||
|
||||
# Insert New Records to IC630M
|
||||
$SQLInsertPrep630M = [];
|
||||
$SQLInsertPrep630M['LLCO'] = $CO; # Company
|
||||
$SQLInsertPrep630M['LLWHNO'] = $value['Warehouse']; # Warehouse
|
||||
// $SQLInsertPrep630M['LLDELNO'] = $MACPKR; # M3 Delivery note number DELETED
|
||||
$SQLInsertPrep630M['LLPPN'] = $value['PartNumber']; # Part Number
|
||||
$SQLInsertPrep630M['LLBALANCE'] = $value['Quantity']; # Quantity
|
||||
$SQLInsertPrep630M['LLSTLC'] = $value['Location']; # Stock location
|
||||
$SQLInsertPrep630M['LLLTNO'] = $value['LotNumber']; # Lot Number
|
||||
$SQLInsertPrep630M['LLMAINTTS'] = now(); # Request time timestamp
|
||||
$SQLInsertPrep630M['LLIZLCF'] = trim($value['LotNumber'])!='' ? '1' : ''; # Lot control flag
|
||||
$SQLInsertPrep630M['LLCMDESC'] = $value['Description']; # Description
|
||||
$SQLInsertPrep630M['LLSPR10A01'] = isset($value['Allocation']) ? $value['Allocation'] : ''; # Allocation
|
||||
$SQLInsertPrep630M['LLSPR15A01'] = isset($value['AllocatedTo']) ? $value['AllocatedTo'] : ''; # AllocatedTo
|
||||
|
||||
DB::connection(config('m3.connection', 'pgsql'))->table('ic630m')->insert($SQLInsertPrep630M);
|
||||
}
|
||||
// dump($SQLInsertPrep);
|
||||
|
||||
#Send Response
|
||||
return response()->json([
|
||||
'code' => '200',
|
||||
'status' => 'Success'
|
||||
]);
|
||||
}
|
||||
else{
|
||||
# Write to Logs Out : Error
|
||||
$MACPKR = isset($MACPKR) ? $MACPKR : '000000';
|
||||
$data = ['SHMACPKR'=>$MACPKR,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> 'X','SHINTBOX'=> '','SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=>'No Records Found in ICM688M2' ,'SHUSER'=> $REQKPKUS,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$CO,'SHWHS'=>$WHS ];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
# Return Error
|
||||
return response()->json([
|
||||
'code' => '405',
|
||||
'status' => 'Error',
|
||||
'message'=> 'No Records Found in ICM688M2'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
# Write to Logs Out : Error
|
||||
$MACPKR = isset($MACPKR) ? $MACPKR : '000000';
|
||||
$data = ['SHMACPKR'=>$MACPKR,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> 'X','SHINTBOX'=> '','SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=>'No URL Parameters Sent','SHUSER'=> $REQKPKUS,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$CO,'SHWHS'=>$WHS ];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
# Return Error
|
||||
return response()->json([
|
||||
'code' => '405',
|
||||
'status' => 'Error',
|
||||
'message'=> 'No URL Parameters Sent'
|
||||
]);
|
||||
}
|
||||
}
|
||||
catch (\Throwable $th) {
|
||||
# Write to Logs Out : Error
|
||||
$MACPKR = isset($MACPKR) ? $MACPKR : '000000';
|
||||
$getCurlErrors = str_contains($th->getMessage(), 'cURL error');
|
||||
if($getCurlErrors){
|
||||
// dd($getCurlErrors);
|
||||
# Write to Logs Out : Failed
|
||||
$data = ['SHMACPKR'=>$MACPKR,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> 'X','SHINTBOX'=> '','SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=>$th->getMessage().' M3-JSN-out'.$IncomingParams ,
|
||||
'SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$CO,'SHWHS'=>$WHS];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
return response()->json([
|
||||
'code'=>'405',
|
||||
'status'=>'error',
|
||||
'message'=>'Curl Error: Communication with M3 Timed Out.'
|
||||
]);
|
||||
}
|
||||
else {
|
||||
# Set SHERROR To Z if Duplicate Key Detected $th
|
||||
# Read The substring from SHDATA after M3-JSN-out
|
||||
$SHERROR = 'X';
|
||||
$word = 'Duplicate key value specified';
|
||||
$position = strpos($th, $word);
|
||||
|
||||
if ($position !== false) {
|
||||
$SHERROR = 'Z';
|
||||
}
|
||||
|
||||
$data = ['SHMACPKR'=>$MACPKR,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> $SHERROR,'SHINTBOX'=> '','SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=>'An Error Occured-'.substr($th,0,300) ,'SHUSER'=> $REQKPKUS,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$CO,'SHWHS'=>$WHS];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
Log::error($th);
|
||||
return response()->json([
|
||||
'code'=>'405',
|
||||
'status'=>'error',
|
||||
'message'=>'Catched Error: '.$th
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
# End M3InventoryReportListURL
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers\API;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use DB;
|
||||
use Config;
|
||||
use Str;
|
||||
use Log;
|
||||
use Http;
|
||||
use Cache;
|
||||
use DateTime;
|
||||
use Smalot\PdfParser\Parser;
|
||||
use File;
|
||||
use Modules\M3\Helpers\Helper;
|
||||
|
||||
class PdfStorage extends Controller
|
||||
{
|
||||
# PdfStorageAPI : PDF file read and save to Cache
|
||||
public function PdfStorageAPI(Request $request){
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('max_input_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOut'));
|
||||
// dd($request->all());
|
||||
# Get the Calling User
|
||||
$SHUSER = m3_user() !== '' ? Str::upper(m3_user()) : 'WebUser';
|
||||
$SHSOURCE = 'PdfStorageAPI';
|
||||
# PDF File PATH
|
||||
$pdfFilePath = Config::get('arrays.PdfPath');
|
||||
try {
|
||||
# Get URL PARAMS
|
||||
$urlParams = count($request->all())>0 ? $request->all() : '';
|
||||
// dd($urlParams);
|
||||
|
||||
$COMPANY = isset($urlParams["COMPANY"]) ? trim($urlParams["COMPANY"]) : ''; # Company
|
||||
$WHS = isset($urlParams["WHS"]) ? trim($urlParams["WHS"]) : ''; # WareHouse
|
||||
$DOCTYPE = isset($urlParams["DOCTYPE"]) ? trim($urlParams["DOCTYPE"]) : ''; # document type (PackingList, CarrierLabel, ContentLabel)
|
||||
$FILENAME = isset($urlParams["FILENAME"]) ? trim($urlParams["FILENAME"]) : ''; # PDF File name
|
||||
$DOCNUM = isset($urlParams["DOCNUM"]) ? trim($urlParams["DOCNUM"]) : ''; # document number (ie the internal box number, the pick list number)
|
||||
$A4MACPKR = isset($urlParams["A4MACPKR"]) ? trim($urlParams["A4MACPKR"]) : ''; # Delivery note number
|
||||
|
||||
if($urlParams!=''){
|
||||
# Key Combination : COMPANY WHS A4MACPKR DOCTYPE DOCNUM
|
||||
# Document type (PackingList, CarrierLabel, ContentLabel)
|
||||
$DELIVERYNO = isset($A4MACPKR) ? $A4MACPKR : '000000';
|
||||
$DELIVERYNO = $DELIVERYNO!="" && $DELIVERYNO!=null ? $DELIVERYNO : '000000';
|
||||
# Write to Logs : Params In
|
||||
$IncomingParams = ['COMPANY'=> $COMPANY,'WHS'=> $WHS,'DOCTYPE'=> $DOCTYPE,'FILENAME'=> $FILENAME,'A4MACPKR'=> $A4MACPKR,'DOCNUM' => $DOCNUM];
|
||||
$data = ['SHMACPKR'=>$DELIVERYNO,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> '','SHINTBOX'=> $DOCNUM,'SHTYPE'=> 'M3-Req-out' ,
|
||||
'SHDATA'=>json_encode($IncomingParams) ,'SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$COMPANY,'SHWHS'=>$WHS ];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
# Make Key and Test Validity
|
||||
if ($A4MACPKR!='' && $DOCTYPE!='' && $DOCNUM!='' && $COMPANY!='' && $WHS!=''){
|
||||
$cacheKey = $A4MACPKR.$DOCTYPE.$DOCNUM.$COMPANY.$WHS;
|
||||
}
|
||||
else{
|
||||
$cacheKey ='';
|
||||
}
|
||||
|
||||
# Read PDF File and Encode to Base64
|
||||
$pdfFileName = $pdfFilePath.$FILENAME.'.pdf';
|
||||
// dd($pdfFileName);
|
||||
// dd(File::exists($pdfFileName));
|
||||
if (File::exists($pdfFileName) && $cacheKey!='') {
|
||||
// dd(File::exists($pdfFileName));
|
||||
|
||||
// Parse PDF file and build necessary objects.
|
||||
$parser = new \Smalot\PdfParser\Parser();
|
||||
|
||||
// $pdf = $parser->parseFile('/www/sentm3test/htdocs/labels/E1232824-10826596.pdf');
|
||||
// dump($pdf);
|
||||
// $text = $pdf->getText();
|
||||
// dump("Text Only");
|
||||
// dump($text);
|
||||
|
||||
$pdfFile = File::get($pdfFileName);
|
||||
|
||||
// Transform content to base64
|
||||
$base64PDF = base64_encode($pdfFile);
|
||||
// Output base64 string
|
||||
// dump($base64PDF);
|
||||
|
||||
# Save Cache
|
||||
Cache::forever($cacheKey, $base64PDF);
|
||||
// Cache::put($cacheKey, $base64PDF, now()->addMinutes(60));
|
||||
|
||||
# Retrieve Cache
|
||||
// $cachedPdfFile = Cache::get($cacheKey);
|
||||
// dump("Retrieve Base64 Encoded PDF saved in Cache:");
|
||||
// dump($cachedPdfFile);
|
||||
// $pdfData = substr($cachedPdfFile,0,50);
|
||||
# remove File from Cache
|
||||
// Cache::put(pdfFileName, 'value', -5);
|
||||
// Cache::forget($pdfFileName);
|
||||
|
||||
# Base64 Decode and Display
|
||||
// $pdf = $parser->parseContent(base64_decode($base64PDF));
|
||||
// $text = $pdf->getText();
|
||||
// dump($text);
|
||||
|
||||
# Write to Logs Out : Success
|
||||
$data = ['SHMACPKR'=>$DELIVERYNO,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> '','SHINTBOX'=> $DOCNUM,'SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=>'PDF File converted to Base64 and Saved to Cache.Key: '.$cacheKey,'SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$COMPANY,'SHWHS'=>$WHS];
|
||||
// dd($data);
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
return response()->json([
|
||||
'code' => '200',
|
||||
'status' => 'Success',
|
||||
'cacheKey'=> $cacheKey
|
||||
// 'PDFData' => $pdfData
|
||||
]);
|
||||
}
|
||||
else {
|
||||
$SHDATA = File::exists($pdfFileName) ? '' : 'PDF File Not Found-';
|
||||
$SHDATA = $cacheKey!='' ? $SHDATA.'' : $SHDATA.'Cache Key is missing Params';
|
||||
|
||||
# Write to Logs Out : Error
|
||||
$data = ['SHMACPKR'=>$DELIVERYNO,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> 'X','SHINTBOX'=> $DOCNUM,'SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=>'An Error Occured -'.$SHDATA,'SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$COMPANY,'SHWHS'=>$WHS];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
# Return Error
|
||||
return response()->json([
|
||||
'code' => '405',
|
||||
'status' => 'Error',
|
||||
'message'=> $SHDATA
|
||||
]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
# Write to Logs Out : Error
|
||||
$DELIVERYNO = isset($DELIVERYNO) ? $DELIVERYNO : '000000';
|
||||
$data = ['SHMACPKR'=>$DELIVERYNO,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> 'X','SHINTBOX'=> '','SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=>'No URL Parameters Sent.','SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$COMPANY,'SHWHS'=>$WHS];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
# Return Error
|
||||
return response()->json([
|
||||
'code' => '405',
|
||||
'status' => 'Error',
|
||||
'message'=> 'No URL Parameters Sent'
|
||||
]);
|
||||
}
|
||||
}
|
||||
catch (\Throwable $th) {
|
||||
// Log::error($th);
|
||||
|
||||
# Write to Logs Out : Error
|
||||
$DELIVERYNO = isset($DELIVERYNO) ? $DELIVERYNO : '000000';
|
||||
$data = ['SHMACPKR'=>$DELIVERYNO,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> 'X','SHINTBOX'=> '','SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=>'An Error Occured - '.substr($th,0,300) ,'SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$COMPANY,'SHWHS'=>$WHS];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
return response()->json([
|
||||
'code'=>'405',
|
||||
'status'=>'error',
|
||||
'message'=>'Catched Error: '.$th
|
||||
]);
|
||||
}
|
||||
}
|
||||
# End PdfStorageAPI
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers\API;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use DB;
|
||||
use Config;
|
||||
use Str;
|
||||
use Log;
|
||||
use Http;
|
||||
use Cache;
|
||||
use DateTime;
|
||||
use Smalot\PdfParser\Parser;
|
||||
use File;
|
||||
use Modules\M3\Helpers\Helper;
|
||||
|
||||
class ReplenAPI extends Controller
|
||||
{
|
||||
# M3Replenishement with URL Params
|
||||
public function M3InventoryReportReplen(Request $request){
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('max_input_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOut'));
|
||||
|
||||
// dd($request->all());
|
||||
// Log::info( $request->all() );
|
||||
# Get The Calling User
|
||||
$SHUSER = m3_user() !== '' ? Str::upper(m3_user()) : 'WebUser';
|
||||
$MACPKR = isset($MACPKR) ? $MACPKR : '000000';
|
||||
$SHSOURCE = 'M3InventoryReportReplen';
|
||||
$M3Errors = '';
|
||||
|
||||
try {
|
||||
# Get Json Contents
|
||||
$urlParams = count($request->all())>0 ? $request->all() : '';
|
||||
|
||||
$CO = isset($urlParams["CO"]) ? $urlParams["CO"] : '';
|
||||
$WHS = isset($urlParams["WHS"]) ? $urlParams["WHS"] : '';
|
||||
$PARTNO = isset($urlParams["PARTNO"]) ? $urlParams["PARTNO"] : '';
|
||||
$PKLN = isset($urlParams["PKLN"]) ? $urlParams["PKLN"] : '';
|
||||
$REQPKWS = isset($urlParams["REQPKWS"]) ? $urlParams["REQPKWS"] : '';
|
||||
$REQKPKUS = isset($urlParams["REQKPKUS"]) ? $urlParams["REQKPKUS"] : 'WebUser';
|
||||
|
||||
if($urlParams!=''){
|
||||
$IncomingParams = ['CO'=> $CO,'WHS'=> $WHS,'PARTNO'=> $PARTNO,'PKLN'=> $PKLN,'REQPKWS'=> $REQPKWS,'REQKPKUS'=> $REQKPKUS];
|
||||
$IncomingParams = json_encode($IncomingParams);
|
||||
|
||||
# Write to Logs : Params In
|
||||
$data = ['SHMACPKR'=>$MACPKR,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> '','SHINTBOX'=> '','SHTYPE'=> 'M3-Req-out' ,
|
||||
'SHDATA'=>$IncomingParams ,'SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$CO,'SHWHS'=>$WHS ];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
$PART = explode( ',',$PARTNO);
|
||||
foreach( $PART as $key => $value){
|
||||
$PARTS[] = ["PART"=> $value,"LOT"=>""];
|
||||
}
|
||||
// dump($PARTS);
|
||||
|
||||
$JSON = json_encode( ["WHS" => $WHS,"PARTS"=> $PARTS ] );
|
||||
|
||||
# Write to Logs : Params Sent To M3
|
||||
$data = ['SHMACPKR'=>$MACPKR,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> '','SHINTBOX'=> '','SHTYPE'=> 'M3-Req-out' ,
|
||||
'SHDATA'=>'Sent To M3-'.$JSON ,'SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$CO,'SHWHS'=>$WHS ];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
# Get Token
|
||||
$tokenResponse = Helper::checkReceiveTokenV2();
|
||||
$tokenData = $tokenResponse->getData();
|
||||
// dd($IonToken->code);
|
||||
if($tokenData->code=='200'){
|
||||
$IonToken = isset($tokenData->token) ? $tokenData->token : '';
|
||||
}
|
||||
else{
|
||||
$SHDATA = isset($tokenData->message) ? $tokenData->message : '';
|
||||
# Write to Logs : Error
|
||||
$data = ['SHMACPKR'=>$MACPKR,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> 'X','SHINTBOX'=> '','SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=> $SHDATA,'SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$CO,'SHWHS'=>$WHS ];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
return $tokenResponse;
|
||||
}
|
||||
|
||||
# Call ionapi with Params
|
||||
$endPointURL = env('ENDPOINTURL').'APIFLOWS/Sentinel/M3InventoryReportList?ionapiRespStyle=sync';
|
||||
$token = $IonToken;
|
||||
|
||||
$response = Http::
|
||||
withHeaders([
|
||||
'accept' => 'application/json',
|
||||
'Content-Type' => 'application/json'
|
||||
])
|
||||
->withToken($token)
|
||||
->withBody($JSON, 'application/json')
|
||||
->timeout(Config::get('arrays.curlTimeOut'))
|
||||
->retry(3, 100)
|
||||
->post($endPointURL);
|
||||
|
||||
$responseStatusCode = $response->getStatusCode();
|
||||
|
||||
$M3SessionId = $response->hasHeader('x-transaction-id') ? "-sessionID:". $response->header('x-transaction-id') : '-sessionID';
|
||||
|
||||
if ($responseStatusCode =='200') {
|
||||
# Check M3 Response for Errors
|
||||
$M3Errors = '';
|
||||
$responseJSON = $response->getBody()->getContents();
|
||||
$JsonSanytized = Helper::sanityzeString($responseJSON);
|
||||
# Array
|
||||
$responseArray = json_decode($JsonSanytized,true);
|
||||
// LOG::info( $responseArray);
|
||||
$responseTMP = $responseArray['result'];
|
||||
// LOG::info($responseTMP);
|
||||
}
|
||||
else{
|
||||
$M3Errors = 'Error: No Response from M3';
|
||||
}
|
||||
|
||||
# Validate response From M3
|
||||
if ($M3Errors!='') {
|
||||
# Write to Logs : Error
|
||||
$data = ['SHMACPKR'=>$MACPKR,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> 'X','SHINTBOX'=> '','SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=>$responseStatusCode.'-'.$M3Errors.$M3SessionId ,'SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$CO,'SHWHS'=>$WHS ];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
# Send Response
|
||||
return response()->json([
|
||||
'code'=>'405',
|
||||
'status'=>'error',
|
||||
'message'=>'Error: No Response from M3'
|
||||
]);
|
||||
}
|
||||
else{
|
||||
# Write to Logs : JSON
|
||||
$data = ['SHMACPKR'=>$MACPKR,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> '','SHINTBOX'=> '','SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=>$responseStatusCode.'-'.$JsonSanytized.$M3SessionId ,'SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$CO,'SHWHS'=>$WHS ];
|
||||
Helper::logToICM699M($data);
|
||||
}
|
||||
|
||||
$dataToWrite2 = [];
|
||||
foreach ($responseTMP as $key => $value) {
|
||||
// dump($value);
|
||||
$dataToWrite = [];
|
||||
|
||||
foreach ($value as $key2 => $content) {
|
||||
if($key2!='Locations'){
|
||||
$dataToWrite[$key2] = $content;
|
||||
}
|
||||
else{
|
||||
foreach ($content as $key3 => $content2) {
|
||||
//dump($content2);
|
||||
$dataToWrite2[] = array_merge($dataToWrite,$content2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// LOG::info($dataToWrite2);
|
||||
|
||||
# Delete Old Records from IC630M
|
||||
foreach ($dataToWrite2 as $key => $value) {
|
||||
$ICM630MDeleteSQL = DB::connection(config('m3.connection', 'pgsql'))->table('ic630m')
|
||||
->where('LLCO',$CO)
|
||||
->where('LLWHNO',$WHS)
|
||||
->where('LLPPN',trim($value['PartNumber']))
|
||||
->delete();
|
||||
}
|
||||
|
||||
foreach ($dataToWrite2 as $key => $value) {
|
||||
# Check if Location exist in DE640M $value['Location']
|
||||
$DE640MSQLSEL = DB::connection(config('m3.connection', 'pgsql'))->table('de640m')
|
||||
->where('LVCO',$CO)
|
||||
->where('WSELOC',$value['Warehouse'])
|
||||
->where('VLOCID',$value['Location'])
|
||||
->first();
|
||||
// dd($DE640MSQLSEL);
|
||||
|
||||
$LocationExist = isset($DE640MSQLSEL->VLOCID) ? trim($DE640MSQLSEL->VLOCID) : '';
|
||||
$WHExist = isset($DE640MSQLSEL->WSELOC) ? trim($DE640MSQLSEL->WSELOC) : '';
|
||||
$COExist = isset($DE640MSQLSEL->LVCO) ? trim($DE640MSQLSEL->LVCO) : '';
|
||||
// dd($LocationExist .': '.$WHExist.': '.$COExist);
|
||||
|
||||
# if No records Founds insert New Record
|
||||
if ( $LocationExist=='' && $WHExist=='' && $COExist=='' ) {
|
||||
$SQLInsertPrep640M['LVCO'] = $CO; // Company
|
||||
$SQLInsertPrep640M['WSELOC'] = $value['Warehouse'];
|
||||
// $SQLInsertPrep640M['LVUSD3'] = $value['']; // Pallet Size : Not Found in M3 JSON
|
||||
$SQLInsertPrep640M['VLOCID'] = $value['Location']; // Stock location
|
||||
$SQLInsertPrep640M['LVSEQN'] = $value['LocationSeq'];
|
||||
$SQLInsertPrep640M['LVUSD2'] = $value['LocationType'];
|
||||
$SQLInsertPrep640M['LVZONE'] = $value['Zone']; // Warehouse zone
|
||||
$SQLInsertPrep640M['LVMAINTTS'] = now(); // Last maintained time stamp
|
||||
|
||||
DB::connection(config('m3.connection', 'pgsql'))->table('de640m')->insert($SQLInsertPrep640M);
|
||||
}
|
||||
# Update
|
||||
else {
|
||||
$SQLUpdatePrep640M['LVSEQN'] = $value['LocationSeq'];
|
||||
$SQLUpdatePrep640M['LVUSD2'] = $value['LocationType'];
|
||||
$SQLUpdatePrep640M['LVZONE'] = $value['Zone'];
|
||||
$SQLUpdatePrep640M['LVMAINTTS'] = now();
|
||||
|
||||
DB::connection(config('m3.connection', 'pgsql'))->table('de640m')
|
||||
->where('LVCO',$CO)
|
||||
->where('WSELOC',$value['Warehouse'])
|
||||
->where('VLOCID',$value['Location'])
|
||||
->update($SQLUpdatePrep640M);
|
||||
}
|
||||
|
||||
# Insert New Records to IC630M
|
||||
$SQLInsertPrep630M = [];
|
||||
$SQLInsertPrep630M['LLCO'] = $CO; # Company
|
||||
$SQLInsertPrep630M['LLWHNO'] = $value['Warehouse']; # Warehouse
|
||||
$SQLInsertPrep630M['LLPPN'] = $value['PartNumber']; # Part Number
|
||||
$SQLInsertPrep630M['LLBALANCE'] = $value['Quantity']; # Quantity
|
||||
$SQLInsertPrep630M['LLSTLC'] = $value['Location']; # Stock location
|
||||
$SQLInsertPrep630M['LLLTNO'] = $value['LotNumber']; # Lot Number
|
||||
$SQLInsertPrep630M['LLMAINTTS'] = now(); # Request time timestamp
|
||||
$SQLInsertPrep630M['LLIZLCF'] = trim($value['LotNumber'])!='' ? '1' : ''; # Lot control flag
|
||||
$SQLInsertPrep630M['LLSPR10A01'] = $value['Allocation']; # Allocation
|
||||
$SQLInsertPrep630M['LLSPR15A01'] = $value['AllocatedTo']; # AllocatedTo
|
||||
|
||||
$DescSanytized = Helper::sanityzeString($value['Description']);
|
||||
// $DescSanytized = str_replace(['–','\u20131'], '-',$value['Description']);
|
||||
$SQLInsertPrep630M['LLCMDESC'] = $DescSanytized; // Description
|
||||
|
||||
DB::connection(config('m3.connection', 'pgsql'))->table('ic630m')->insert($SQLInsertPrep630M);
|
||||
}
|
||||
// dump($SQLInsertPrep);
|
||||
|
||||
#Send Response
|
||||
return response()->json([
|
||||
'code' => '200',
|
||||
'status' => 'Success'
|
||||
]);
|
||||
}
|
||||
else {
|
||||
# Write to Logs Out : Error
|
||||
$MACPKR = isset($MACPKR) ? $MACPKR : '000000';
|
||||
$data = ['SHMACPKR'=>$MACPKR,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> 'X','SHINTBOX'=> '','SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=>'No URL Parameters Sent','SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$CO,'SHWHS'=>$WHS ];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
# Return Error
|
||||
return response()->json([
|
||||
'code' => '405',
|
||||
'status' => 'Error',
|
||||
'message'=> 'No URL Parameters Sent'
|
||||
]);
|
||||
}
|
||||
}
|
||||
catch (\Throwable $th) {
|
||||
# Write to Logs Out : Error
|
||||
$MACPKR = isset($MACPKR) ? $MACPKR : '000000';
|
||||
|
||||
$getCurlErrors = str_contains($th->getMessage(), 'cURL error');
|
||||
if($getCurlErrors){
|
||||
// dd($getCurlErrors);
|
||||
# Write to Logs Out : Failed
|
||||
$data = ['SHMACPKR'=>$MACPKR,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> 'X','SHINTBOX'=> '','SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=> 'Curl Error: Communication with M3 Timed Out'.' M3-JSN-out'.$IncomingParams,'SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$CO,'SHWHS'=>$WHS];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
return response()->json([
|
||||
'code'=>'405',
|
||||
'status'=>'error',
|
||||
'message'=>'Curl Error: Communication with M3 Timed Out.'
|
||||
]);
|
||||
}
|
||||
else {
|
||||
# Set SHERROR To Z if Duplicate Key Detected $th
|
||||
# Read The substring from SHDATA after M3-JSN-out
|
||||
$SHERROR = 'X';
|
||||
$word = 'Duplicate key value specified';
|
||||
$position = strpos($th, $word);
|
||||
|
||||
if ($position !== false) {
|
||||
$SHERROR = 'Z';
|
||||
}
|
||||
|
||||
$data = ['SHMACPKR'=>$MACPKR,'SHDT'=> date('Y-m-d'),'SHTIME'=> date('H:i:s') ,'SHERROR'=> $SHERROR,'SHINTBOX'=> '','SHTYPE'=> 'M3-Res-out' ,
|
||||
'SHDATA'=>'An Error Occured - '.substr($th,0,300) ,'SHUSER'=> $SHUSER,'SHSOURCE'=> $SHSOURCE,'SHCO'=>$CO,'SHWHS'=>$WHS];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
// Log::error($th);
|
||||
return response()->json([
|
||||
'code'=>'405',
|
||||
'status'=>'error',
|
||||
'message'=>'Catched Error: '.$th
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
# End M3InventoryReportReplen
|
||||
}
|
||||
@@ -0,0 +1,712 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers\API;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use DB;
|
||||
use Config;
|
||||
use Str;
|
||||
use Log;
|
||||
use Http;
|
||||
use Cache;
|
||||
use DateTime;
|
||||
use Smalot\PdfParser\Parser;
|
||||
use File;
|
||||
use Modules\M3\Helpers\Helper;
|
||||
|
||||
class TransferAPI extends Controller
|
||||
{
|
||||
# TransferAPIURL : with URL PARAMS
|
||||
public function TransferAPIURL(Request $request)
|
||||
{
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('max_input_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOut'));
|
||||
// dd($request->all());
|
||||
|
||||
# Get the Calling User
|
||||
$SHUSER = m3_user() !== '' ? Str::upper(m3_user()) : 'WebUser';
|
||||
# Set SHSOURCE
|
||||
$SHSOURCE = 'TransferAPIURL';
|
||||
$M3Errors = '';
|
||||
|
||||
# Get URL PARAMS
|
||||
$urlParams = count($request->all()) > 0 ? $request->all() : '';
|
||||
$DIVI = isset($urlParams["COMPANY"]) ? $urlParams["COMPANY"] : '';
|
||||
$WHS = isset($urlParams["WHS"]) ? $urlParams["WHS"] : '';
|
||||
|
||||
try {
|
||||
if ($urlParams != '') {
|
||||
$PART = isset($urlParams["PART"]) ? $urlParams["PART"] : '';
|
||||
$LOCATIONFROM = isset($urlParams["LOCATIONFROM"]) ? $urlParams["LOCATIONFROM"] : '';
|
||||
$LOCATIONTO = isset($urlParams["LOCATIONTO"]) ? $urlParams["LOCATIONTO"] : '';
|
||||
$QUANTITY = isset($urlParams["QUANTITY"]) ? $urlParams["QUANTITY"] : '';
|
||||
$ORDERCATEGORY = isset($urlParams["ORDERCATEGORY"]) ? $urlParams["ORDERCATEGORY"] : '';
|
||||
$LOTNUMBER = isset($urlParams["LOTNUMBER"]) ? $urlParams["LOTNUMBER"] : "";
|
||||
$CONUMBER = isset($urlParams["CONUMBER"]) ? $urlParams["CONUMBER"] : '';
|
||||
$COLINENO = isset($urlParams["COLINENO"]) ? $urlParams["COLINENO"] : '';
|
||||
$DELIVERYNO = isset($urlParams["DELIVERYNO"]) ? $urlParams["DELIVERYNO"] : '000000';
|
||||
$PICKLISTSUFFIX = isset($urlParams["PICKLISTSUFFIX"]) ? $urlParams["PICKLISTSUFFIX"] : '';
|
||||
$ENDFLAG = isset($urlParams["ENDFLAG"]) ? $urlParams["ENDFLAG"] : '';
|
||||
$TYPE = isset($urlParams["TYPE"]) ? $urlParams["TYPE"] : '';
|
||||
$COLINESUFFIX = isset($urlParams["COLINESUFFIX"]) ? $urlParams["COLINESUFFIX"] : '';
|
||||
|
||||
# TYPE :
|
||||
# DeliveryNote
|
||||
# S15
|
||||
# CloseShipment
|
||||
# COCharge
|
||||
# Replenishment
|
||||
# Move
|
||||
|
||||
# ORDERCATEGORY : Order Category
|
||||
# 1 = Material to manufacturing order
|
||||
# 3 = Customer Order
|
||||
# 4 = Requisition Order
|
||||
# 5 = Distribution Order
|
||||
# 9 = Move order
|
||||
|
||||
|
||||
$DELIVERYNO = isset($DELIVERYNO) ? $DELIVERYNO : '000000';
|
||||
|
||||
$TRANSTYPE = isset($urlParams["TRANSTYPE"]) ? $urlParams["TRANSTYPE"] : ''; # R for Retry
|
||||
$SHDT = isset($urlParams["SHDT"]) ? $urlParams["SHDT"] : '';
|
||||
$SHTIME = isset($urlParams["SHTIME"]) ? $urlParams["SHTIME"] : '';
|
||||
$SHTYPE = isset($urlParams["SHTYPE"]) ? $urlParams["SHTYPE"] : '';
|
||||
|
||||
# Retry Transfer
|
||||
if ($TRANSTYPE == 'R') {
|
||||
# $t = strtotime($SHTIME);
|
||||
# $SHTIMEHM = date('H:i',$t);
|
||||
# dd($SHTIMEHM);
|
||||
# Get the record that contain the payload
|
||||
$ICM699MS = DB::connection(config('m3.connection', 'pgsql'))->table('icm699m')
|
||||
->select('SHDATA')
|
||||
->where('SHMACPKR', $DELIVERYNO)
|
||||
->where('SHDT', $SHDT)
|
||||
->where('SHTIME', $SHTIME)
|
||||
# ->whereRaw("VARCHAR_FORMAT (TIMESTAMP (CURRENT DATE) + MIDNIGHT_SECONDS (SHTIME) SECONDS, 'HH24:MI') = ?", [$SHTIMEHM])
|
||||
->where('SHCO', $DIVI)
|
||||
->where('SHWHS', $WHS)
|
||||
->where('SHSOURCE', $SHSOURCE)
|
||||
->where('SHERROR', 'X')
|
||||
->where('SHTYPE', $SHTYPE)
|
||||
->first();
|
||||
// dump($ICM699MS->SHDATA);
|
||||
|
||||
# Read The substring from SHDATA after M3-JSN-out
|
||||
$word = 'M3-JSN-out';
|
||||
$SHDATA = isset($ICM699MS->SHDATA) ? $ICM699MS->SHDATA : '';
|
||||
$SHDATAJSON = "";
|
||||
$position = strpos($SHDATA, $word);
|
||||
# Also Read CommTCP_read
|
||||
$word2 = 'url:http://127.0.0.1:10005/api/TransferAPIURL?';
|
||||
$SHDATA2 = isset($ICM699MS->SHDATA) ? $ICM699MS->SHDATA : '';
|
||||
$position2 = strpos($SHDATA2, $word2);
|
||||
|
||||
if ($position !== false) {
|
||||
$SHDATAJSON = substr($SHDATA, $position + strlen($word));
|
||||
} else if ($position2 !== false) {
|
||||
$SHDATAJSONS = substr($SHDATA2, $position2 + strlen($word2));
|
||||
$SHDATAJSONA = [];
|
||||
parse_str($SHDATAJSONS, $SHDATAJSONA);
|
||||
$SHDATAJSON = json_encode($SHDATAJSONA);
|
||||
}
|
||||
# Find the position of the opening and closing curly braces
|
||||
$startPos = strpos($SHDATAJSON, '{');
|
||||
$endPos = strrpos($SHDATAJSON, '}');
|
||||
# Extract the substring within the curly braces
|
||||
$SHDATAJSON = substr($SHDATAJSON, $startPos, $endPos - $startPos + 1);
|
||||
// dd($SHDATAJSON);
|
||||
|
||||
$JSONTR = $SHDATAJSON != '' ? json_decode($SHDATAJSON) : '';
|
||||
// dd($JSONTR);
|
||||
|
||||
if ($JSONTR != '') {
|
||||
$PART = isset($JSONTR->PART) ? $JSONTR->PART : '';
|
||||
$LOCATIONFROM = isset($JSONTR->LOCATIONFROM) ? $JSONTR->LOCATIONFROM : '';
|
||||
$LOCATIONTO = isset($JSONTR->LOCATIONTO) ? $JSONTR->LOCATIONTO : '';
|
||||
$QUANTITY = isset($JSONTR->QUANTITY) ? $JSONTR->QUANTITY : '';
|
||||
$ORDERCATEGORY = isset($JSONTR->ORDERCATEGORY) ? $JSONTR->ORDERCATEGORY : '';
|
||||
$LOTNUMBER = isset($JSONTR->LOTNUMBER) ? $JSONTR->LOTNUMBER : "";
|
||||
$CONUMBER = isset($JSONTR->CONUMBER) ? $JSONTR->CONUMBER : '';
|
||||
$COLINENO = isset($JSONTR->COLINENO) ? $JSONTR->COLINENO : '';
|
||||
$DELIVERYNO = isset($JSONTR->DELIVERYNO) ? $JSONTR->DELIVERYNO : '000000';
|
||||
$PICKLISTSUFFIX = isset($JSONTR->PICKLISTSUFFIX) ? $JSONTR->PICKLISTSUFFIX : '';
|
||||
$ENDFLAG = isset($JSONTR->ENDFLAG) ? $JSONTR->ENDFLAG : '';
|
||||
$TYPE = isset($JSONTR->TYPE) ? $JSONTR->TYPE : '';
|
||||
$COLINESUFFIX = isset($JSONTR->COLINESUFFIX) ? $JSONTR->COLINESUFFIX : '';
|
||||
}
|
||||
// dd($JSONTR);
|
||||
|
||||
# Set SHERROR to Z in ICM699M
|
||||
$ICM699MU = DB::connection(config('m3.connection', 'pgsql'))->table('icm699m')
|
||||
->where('SHMACPKR', $DELIVERYNO)
|
||||
->where('SHDT', $SHDT)
|
||||
->where('SHTIME', $SHTIME)
|
||||
->where('SHCO', $DIVI)
|
||||
->where('SHWHS', $WHS)
|
||||
->where('SHSOURCE', $SHSOURCE)
|
||||
->where('SHERROR', 'X')
|
||||
->where('SHTYPE', $SHTYPE)
|
||||
->update(["SHERROR" => "Z", "SHACKUSER" => $SHUSER, "SHACKDATE" => date('Y-m-d'), "SHACKTIME" => date('H:i:s')]);
|
||||
}
|
||||
|
||||
# Part Exists : proceed
|
||||
if ($PART != '') {
|
||||
# Read from ICM688M2
|
||||
# Get Parts And Lots from ICM688M2
|
||||
$ICM688M2SLTMP = DB::connection(config('m3.connection', 'pgsql'))->table('icm688m2')
|
||||
->select('A5BRADLN', 'A5PKSFX', 'A5PLANT', 'A5SENTPKR')
|
||||
->distinct()
|
||||
->where('A5CO', $DIVI)
|
||||
->where('A5WHS', $WHS)
|
||||
->where('A5MACPKR', $DELIVERYNO);
|
||||
|
||||
# Get Pack Lines
|
||||
if ($COLINENO != '') {
|
||||
$ICM688M2SLTMP->where('A5PKLN', $COLINENO);
|
||||
}
|
||||
$ICM688M2SL = $ICM688M2SLTMP->first();
|
||||
// dd($ICM688M2SL->A5BRADLN);
|
||||
|
||||
$A5BRADLINE = isset($ICM688M2SL->A5BRADLN) ? $ICM688M2SL->A5BRADLN : '';
|
||||
$COLINESUFFIX = isset($ICM688M2SL->A5PKSFX) ? $ICM688M2SL->A5PKSFX : ''; # Case 551 : $COLINESUFFIX
|
||||
$A5PLANT = isset($ICM688M2SL->A5PLANT) ? $ICM688M2SL->A5PLANT : '';
|
||||
$A5SENTPKR = isset($ICM688M2SL->A5SENTPKR) ? $ICM688M2SL->A5SENTPKR : '';
|
||||
|
||||
$JSONIN = json_encode([
|
||||
"DIVI" => $DIVI,
|
||||
"WHS" => $WHS,
|
||||
"PART" => $PART,
|
||||
"LOCATIONFROM" => $LOCATIONFROM,
|
||||
"LOCATIONTO" => $LOCATIONTO,
|
||||
"QUANTITY" => $QUANTITY,
|
||||
"ORDERCATEGORY" => $ORDERCATEGORY,
|
||||
"LOTNUMBER" => $LOTNUMBER,
|
||||
"CONUMBER" => $CONUMBER,
|
||||
"COLINENO" => $COLINENO,
|
||||
"DELIVERYNO" => $DELIVERYNO,
|
||||
"PICKLISTSUFFIX" => $PICKLISTSUFFIX,
|
||||
"ENDFLAG" => $ENDFLAG,
|
||||
"TYPE" => $TYPE,
|
||||
"COLINESUFFIX" => $COLINESUFFIX,
|
||||
], JSON_UNESCAPED_SLASHES);
|
||||
|
||||
$JSON = json_encode([
|
||||
"DIVI" => $DIVI,
|
||||
"WHS" => $WHS,
|
||||
"PART" => $PART,
|
||||
"LOCATIONFROM" => $LOCATIONFROM,
|
||||
"LOCATIONTO" => $LOCATIONTO,
|
||||
"QUANTITY" => $QUANTITY,
|
||||
"ORDERCATEGORY" => $ORDERCATEGORY,
|
||||
"LOTNUMBER" => $LOTNUMBER,
|
||||
"CONUMBER" => $CONUMBER,
|
||||
"COLINENO" => $A5BRADLINE,
|
||||
"DELIVERYNO" => $DELIVERYNO,
|
||||
"PICKLISTSUFFIX" => $PICKLISTSUFFIX,
|
||||
"ENDFLAG" => $ENDFLAG,
|
||||
"TYPE" => $TYPE,
|
||||
"COLINESUFFIX" => $COLINESUFFIX,
|
||||
], JSON_UNESCAPED_SLASHES);
|
||||
// dd($JSON);
|
||||
|
||||
# Write JSON Params to Logs Out
|
||||
$data = ['SHMACPKR' => $DELIVERYNO,
|
||||
'SHDT' => date('Y-m-d'),
|
||||
'SHTIME' => date('H:i:s'),
|
||||
'SHERROR' => '',
|
||||
'SHINTBOX' => '',
|
||||
'SHTYPE' => 'M3-Req-out',
|
||||
'SHDATA' => $JSON,
|
||||
'SHUSER' => $SHUSER,
|
||||
'SHSOURCE' => $SHSOURCE,
|
||||
'SHCO' => $DIVI,
|
||||
'SHWHS' => $WHS
|
||||
];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
# Get Token
|
||||
$tokenResponse = Helper::checkReceiveTokenV2();
|
||||
$tokenData = $tokenResponse->getData();
|
||||
if ($tokenData->code == '200') {
|
||||
$IonToken = isset($tokenData->token) ? $tokenData->token : '';
|
||||
} else {
|
||||
$SHDATA = isset($tokenData->message) ? $tokenData->message : '';
|
||||
# Write to Logs : Error
|
||||
$data = ['SHMACPKR' => $DELIVERYNO,
|
||||
'SHDT' => date('Y-m-d'),
|
||||
'SHTIME' => date('H:i:s'),
|
||||
'SHERROR' => '',
|
||||
'SHINTBOX' => '',
|
||||
'SHTYPE' => 'M3-Res-out',
|
||||
'SHDATA' => $SHDATA,
|
||||
'SHUSER' => $SHUSER,
|
||||
'SHSOURCE' => $SHSOURCE,
|
||||
'SHCO' => $DIVI,
|
||||
'SHWHS' => $WHS
|
||||
];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
return $tokenResponse;
|
||||
}
|
||||
|
||||
# Call ionapi with Params
|
||||
$endPointURL = env('ENDPOINTURL') . 'APIFLOWS/Sentinel/TransferAPI?ionapiRespStyle=sync';
|
||||
$token = $IonToken;
|
||||
|
||||
$response = Http::withHeaders([
|
||||
'accept' => 'application/json',
|
||||
'Content-Type' => 'application/json'
|
||||
])
|
||||
->withToken($token)
|
||||
->withBody($JSON, 'application/json')
|
||||
->timeout(Config::get('arrays.curlTimeOut'))
|
||||
->post($endPointURL);
|
||||
$responseStatusCode = $response->getStatusCode();
|
||||
$M3SessionId = $response->hasHeader('x-transaction-id') ? "-sessionID:" . $response->header('x-transaction-id') : '-sessionID';
|
||||
$M3ResponseTimeTmp = $response->hasHeader('x-response-time') ? ltrim($response->header('x-response-time'), "-") : '0';
|
||||
$M3ResponseTimeTmp2 = floatval($M3ResponseTimeTmp) / 1000; //$M3ResponseTimeTmp / 1000;
|
||||
$dateTime = new DateTime();
|
||||
$dateTime->setTimestamp($M3ResponseTimeTmp2);
|
||||
// dump( $dateTime->format('d/m/Y H:i:s.v') );
|
||||
$M3ResponseTime = $M3ResponseTimeTmp != '' ? '-M3ResponseTime:' . $dateTime->format('d/m/Y H:i:s.v') : '-M3ResponseTime';
|
||||
// dump($M3ResponseTime);
|
||||
$transferStats = $response->transferStats;
|
||||
$M3transferTime = $transferStats->getTransferTime() != null ? "-M3transferTime:" . $transferStats->getTransferTime() : "-M3transferTime";
|
||||
// dd($M3transferTime);
|
||||
|
||||
if ($responseStatusCode == '200') {
|
||||
$responseContents = json_decode($response->getBody()->getContents());
|
||||
$responseResult = $responseContents->result;
|
||||
$M3JSONResponse = json_encode($responseContents);
|
||||
# Check M3 Response for Errors
|
||||
$M3Errors = Helper::checkM3Errors($responseResult);
|
||||
} else {
|
||||
$M3JSONResponse = '';
|
||||
$M3Errors = 'Error: No Response from M3';
|
||||
}
|
||||
|
||||
if ($M3Errors == '') {
|
||||
# Write to Logs Out : Success
|
||||
$data = ['SHMACPKR' => $DELIVERYNO,
|
||||
'SHDT' => date('Y-m-d'),
|
||||
'SHTIME' => date('H:i:s'),
|
||||
'SHERROR' => '',
|
||||
'SHINTBOX' => '',
|
||||
'SHTYPE' => 'M3-Res-out',
|
||||
'SHDATA' => $responseStatusCode . 'TYPE :' . $TYPE . ' Order Category: ' . $ORDERCATEGORY . '-' . $M3JSONResponse . $M3SessionId . $M3ResponseTime . $M3transferTime,
|
||||
'SHUSER' => $SHUSER,
|
||||
'SHSOURCE' => $SHSOURCE,
|
||||
'SHCO' => $DIVI,
|
||||
'SHWHS' => $WHS
|
||||
];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
# Log to ICM799M
|
||||
$ICM799MINS = DB::connection(config('m3.connection', 'pgsql'))->table('icm799m')
|
||||
->insert(["IMDIV" => $DIVI,
|
||||
"IMPLANT" => $A5PLANT,
|
||||
"IMWHS" => $WHS,
|
||||
"IMSENTPKR" => $A5SENTPKR,
|
||||
"IMDELNO" => $DELIVERYNO,
|
||||
"IMORDER" => $CONUMBER,
|
||||
"IMLINE" => $COLINENO,
|
||||
"IMBRADLN" => $A5BRADLINE,
|
||||
"IMSUFFIX" => $PICKLISTSUFFIX,
|
||||
"IMPART" => $PART,
|
||||
"IMLOT" => $LOTNUMBER,
|
||||
"IMQTY" => $QUANTITY,
|
||||
"IMFRLOC" => $LOCATIONFROM,
|
||||
"IMTOLOC" => $LOCATIONTO,
|
||||
"IMDATE" => date('Ymd'),
|
||||
"IMTIME" => date('His')
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'code' => $responseStatusCode,
|
||||
'status' => 'Success'
|
||||
]);
|
||||
} else {
|
||||
# Write to Logs Out : Failed
|
||||
$data = ['SHMACPKR' => $DELIVERYNO,
|
||||
'SHDT' => date('Y-m-d'),
|
||||
'SHTIME' => date('H:i:s'),
|
||||
'SHERROR' => 'X',
|
||||
'SHINTBOX' => '',
|
||||
'SHTYPE' => 'M3-Res-out',
|
||||
'SHDATA' => $responseStatusCode . '-' . $M3Errors . '-TYPE:' . $TYPE . ' Order Category: ' . $ORDERCATEGORY . '-' . $M3JSONResponse .
|
||||
'M3-JSN-out' . $JSONIN . $M3SessionId . $M3ResponseTime . $M3transferTime,
|
||||
'SHUSER' => $SHUSER,
|
||||
'SHSOURCE' => $SHSOURCE,
|
||||
'SHCO' => $DIVI,
|
||||
'SHWHS' => $WHS
|
||||
];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
return response()->json([
|
||||
'code' => '206',
|
||||
'status' => 'Error',
|
||||
'message' => $responseStatusCode . '-' . $M3Errors . '- TYPE :' . $TYPE . ' Order Category: ' . $ORDERCATEGORY . '-' . $M3JSONResponse
|
||||
]);
|
||||
}
|
||||
}
|
||||
# Part Does not Exist : Failure
|
||||
else {
|
||||
# Return Error
|
||||
return response()->json([
|
||||
'code' => '405',
|
||||
'status' => 'Error',
|
||||
'message' => 'Json Payload Not Valid, possible cause: Retry butto was clicked by another user.'
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
# Write to Logs Out : Error
|
||||
$DELIVERYNO = isset($DELIVERYNO) ? $DELIVERYNO : '000000';
|
||||
$data = ['SHMACPKR' => $DELIVERYNO,
|
||||
'SHDT' => date('Y-m-d'),
|
||||
'SHTIME' => date('H:i:s'),
|
||||
'SHERROR' => 'X',
|
||||
'SHINTBOX' => '',
|
||||
'SHTYPE' => 'M3-Res-out',
|
||||
'SHDATA' => 'No URL Parameters Sent',
|
||||
'SHUSER' => $SHUSER,
|
||||
'SHSOURCE' => $SHSOURCE,
|
||||
'SHCO' => $DIVI,
|
||||
'SHWHS' => $WHS
|
||||
];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
# Return Error
|
||||
return response()->json([
|
||||
'code' => '405',
|
||||
'status' => 'Error',
|
||||
'message' => 'No URL Parameters Sent'
|
||||
]);
|
||||
}
|
||||
} catch (\Throwable $th) {
|
||||
// Log::error($th);
|
||||
$getCurlErrors = str_contains($th->getMessage(), 'cURL error');
|
||||
if ($getCurlErrors) {
|
||||
# Write to Logs Out : Failed
|
||||
$data = ['SHMACPKR' => $DELIVERYNO,
|
||||
'SHDT' => date('Y-m-d'),
|
||||
'SHTIME' => date('H:i:s'),
|
||||
'SHERROR' => 'X',
|
||||
'SHINTBOX' => '',
|
||||
'SHTYPE' => 'M3-Res-out',
|
||||
'SHDATA' => 'Curl Error: Communication with M3 Timed Out' . ' M3-JSN-out' . $JSONIN,
|
||||
'SHUSER' => $SHUSER,
|
||||
'SHSOURCE' => $SHSOURCE,
|
||||
'SHCO' => $DIVI,
|
||||
'SHWHS' => $WHS
|
||||
];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
return response()->json([
|
||||
'code' => '405',
|
||||
'status' => 'error',
|
||||
'message' => 'Curl Error: Communication with M3 Timed Out.'
|
||||
]);
|
||||
} else {
|
||||
# Write to Logs Out : Error
|
||||
$DELIVERYNO = isset($DELIVERYNO) ? $DELIVERYNO : '000000';
|
||||
$data = ['SHMACPKR' => $DELIVERYNO,
|
||||
'SHDT' => date('Y-m-d'),
|
||||
'SHTIME' => date('H:i:s'),
|
||||
'SHERROR' => 'X',
|
||||
'SHINTBOX' => '',
|
||||
'SHTYPE' => 'M3-Err-out',
|
||||
'SHDATA' => 'An Error Occured - ' . substr($th, 0, 300),
|
||||
'SHUSER' => $SHUSER,
|
||||
'SHSOURCE' => $SHSOURCE,
|
||||
'SHCO' => $DIVI,
|
||||
'SHWHS' => $WHS
|
||||
];
|
||||
Helper::logToICM699M($data);
|
||||
Log::error($th);
|
||||
|
||||
return response()->json([
|
||||
'code' => '405',
|
||||
'status' => 'error',
|
||||
'message' => 'Uncaught Error'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
# End TransferAPIURL
|
||||
|
||||
# UpdateShipmentNumber : with URL PARAMS
|
||||
public function UpdateShipmentNumber(Request $request)
|
||||
{
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('max_input_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOut'));
|
||||
// dd($request->all());
|
||||
|
||||
# Get the Calling User
|
||||
$SHUSER = m3_user() !== '' ? Str::upper(m3_user()) : 'WebUser';
|
||||
# Set SHSOURCE
|
||||
$SHSOURCE = 'UpdateShipmentNumber';
|
||||
$M3Errors = '';
|
||||
|
||||
# Get URL PARAMS
|
||||
$urlParams = count($request->all()) > 0 ? $request->all() : '';
|
||||
$DIVI = isset($urlParams["COMPANY"]) ? $urlParams["COMPANY"] : '';
|
||||
$WHS = isset($urlParams["WHS"]) ? $urlParams["WHS"] : '';
|
||||
$PLANT = isset($urlParams["PLANT"]) ? $urlParams["PLANT"] : '';
|
||||
// dump($urlParams);
|
||||
|
||||
try {
|
||||
if ($urlParams != '') {
|
||||
$A4SPR15A01 = isset($urlParams["A4SPR15A01"]) ? $urlParams["A4SPR15A01"] : '';
|
||||
$DELIVERYNO = isset($urlParams["DELIVERYNO"]) ? $urlParams["DELIVERYNO"] : '';
|
||||
$TYPE = 'UpdateShipmentNumber';
|
||||
$allMacpkrs = [];
|
||||
// dd($A4SPR15A01);
|
||||
|
||||
if ($A4SPR15A01 != '') {
|
||||
# Read from ICM688M1
|
||||
$ICM688M1SLTMP = DB::connection(config('m3.connection', 'pgsql'))->table('icm688m1')
|
||||
->select('A4MACPKR')
|
||||
->where('A4CO', $DIVI)
|
||||
->where('A4WHS', $WHS)
|
||||
->where('A4PLANT', $PLANT)
|
||||
->where('A4SPR15A01', $A4SPR15A01);
|
||||
|
||||
|
||||
# Get Macpikers also if sent as Parameter
|
||||
if ($DELIVERYNO != '') {
|
||||
$ICM688M1SLTMP->where('A4MACPKR', $DELIVERYNO);
|
||||
}
|
||||
$ICM688M1SL = $ICM688M1SLTMP->get();
|
||||
# Loop ICM688M1 to get all A4MACPKR
|
||||
foreach ($ICM688M1SL as $key => $ICM688M1) {
|
||||
$allMacpkrs[] = $ICM688M1->A4MACPKR;
|
||||
}
|
||||
}
|
||||
|
||||
# A4SPR15A01 Exists : proceed
|
||||
if ($A4SPR15A01 != '' && count($allMacpkrs)>0) {
|
||||
$JSON = json_encode([
|
||||
"DIVI" => $DIVI,
|
||||
"WHS" => $WHS,
|
||||
"ShipmentNumber" => [
|
||||
"Number" => $A4SPR15A01,
|
||||
"DeliveryNumbers" => $allMacpkrs
|
||||
],
|
||||
"TYPE" => $TYPE,
|
||||
"ENDFLAG" => "",
|
||||
|
||||
], JSON_UNESCAPED_SLASHES);
|
||||
// dd($JSON);
|
||||
|
||||
# Write JSON Params to Logs Out
|
||||
$data = ['SHMACPKR' => $DELIVERYNO,
|
||||
'SHDT' => date('Y-m-d'),
|
||||
'SHTIME' => date('H:i:s'),
|
||||
'SHERROR' => '',
|
||||
'SHINTBOX' => '',
|
||||
'SHTYPE' => 'M3-Req-out',
|
||||
'SHDATA' => $JSON,
|
||||
'SHUSER' => $SHUSER,
|
||||
'SHSOURCE' => $SHSOURCE,
|
||||
'SHCO' => $DIVI,
|
||||
'SHWHS' => $WHS
|
||||
];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
# Get Token
|
||||
$tokenResponse = Helper::checkReceiveTokenV2();
|
||||
$tokenData = $tokenResponse->getData();
|
||||
if ($tokenData->code == '200') {
|
||||
$IonToken = isset($tokenData->token) ? $tokenData->token : '';
|
||||
} else {
|
||||
$SHDATA = isset($tokenData->message) ? $tokenData->message : '';
|
||||
# Write to Logs : Error
|
||||
$data = ['SHMACPKR' => $DELIVERYNO,
|
||||
'SHDT' => date('Y-m-d'),
|
||||
'SHTIME' => date('H:i:s'),
|
||||
'SHERROR' => '',
|
||||
'SHINTBOX' => '',
|
||||
'SHTYPE' => 'M3-Res-out',
|
||||
'SHDATA' => $SHDATA,
|
||||
'SHUSER' => $SHUSER,
|
||||
'SHSOURCE' => $SHSOURCE,
|
||||
'SHCO' => $DIVI,
|
||||
'SHWHS' => $WHS
|
||||
];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
return $tokenResponse;
|
||||
}
|
||||
|
||||
# Call ionapi with Params
|
||||
$endPointURL = env('ENDPOINTURL') . 'APIFLOWS/Sentinel/TransferAPI?ionapiRespStyle=sync';
|
||||
$token = $IonToken;
|
||||
|
||||
$response = Http::withHeaders([
|
||||
'accept' => 'application/json',
|
||||
'Content-Type' => 'application/json'
|
||||
])
|
||||
->withToken($token)
|
||||
->withBody($JSON, 'application/json')
|
||||
->timeout(Config::get('arrays.curlTimeOut'))
|
||||
->post($endPointURL);
|
||||
$responseStatusCode = $response->getStatusCode();
|
||||
$M3SessionId = $response->hasHeader('x-transaction-id') ? "-sessionID:" . $response->header('x-transaction-id') : '-sessionID';
|
||||
$M3ResponseTimeTmp = $response->hasHeader('x-response-time') ? ltrim($response->header('x-response-time'), "-") : '0';
|
||||
$M3ResponseTimeTmp2 = floatval($M3ResponseTimeTmp) / 1000; //$M3ResponseTimeTmp / 1000;
|
||||
$dateTime = new DateTime();
|
||||
$dateTime->setTimestamp($M3ResponseTimeTmp2);
|
||||
$M3ResponseTime = $M3ResponseTimeTmp != '' ? '-M3ResponseTime:' . $dateTime->format('d/m/Y H:i:s.v') : '-M3ResponseTime';
|
||||
$transferStats = $response->transferStats;
|
||||
$M3transferTime = $transferStats->getTransferTime() != null ? "-M3transferTime:" . $transferStats->getTransferTime() : "-M3transferTime";
|
||||
|
||||
if ($responseStatusCode == '200') {
|
||||
$responseContents = json_decode($response->getBody()->getContents());
|
||||
$responseResult = $responseContents->result;
|
||||
$M3JSONResponse = json_encode($responseContents);
|
||||
# Check M3 Response for Errors
|
||||
$M3Errors = Helper::checkM3Errors($responseResult);
|
||||
} else {
|
||||
$M3JSONResponse = '';
|
||||
$M3Errors = 'Error: No Response from M3';
|
||||
}
|
||||
|
||||
if ($M3Errors == '') {
|
||||
# Write to Logs Out : Success
|
||||
$data = ['SHMACPKR' => $DELIVERYNO,
|
||||
'SHDT' => date('Y-m-d'),
|
||||
'SHTIME' => date('H:i:s'),
|
||||
'SHERROR' => '',
|
||||
'SHINTBOX' => '',
|
||||
'SHTYPE' => 'M3-Res-out',
|
||||
'SHDATA' => $responseStatusCode . 'TYPE :' . $TYPE . '-' . $M3JSONResponse . $M3SessionId . $M3ResponseTime . $M3transferTime,
|
||||
'SHUSER' => $SHUSER,
|
||||
'SHSOURCE' => $SHSOURCE,
|
||||
'SHCO' => $DIVI,
|
||||
'SHWHS' => $WHS
|
||||
];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
return response()->json([
|
||||
'code' => $responseStatusCode,
|
||||
'status' => 'Success'
|
||||
]);
|
||||
} else {
|
||||
# Write to Logs Out : Failed
|
||||
$data = ['SHMACPKR' => $DELIVERYNO,
|
||||
'SHDT' => date('Y-m-d'),
|
||||
'SHTIME' => date('H:i:s'),
|
||||
'SHERROR' => 'X',
|
||||
'SHINTBOX' => '',
|
||||
'SHTYPE' => 'M3-Res-out',
|
||||
'SHDATA' => $responseStatusCode . '-' . $M3Errors . '-TYPE:' . $TYPE . '-' . $M3JSONResponse .
|
||||
'M3-JSN-out' . $JSON . $M3SessionId . $M3ResponseTime . $M3transferTime,
|
||||
'SHUSER' => $SHUSER,
|
||||
'SHSOURCE' => $SHSOURCE,
|
||||
'SHCO' => $DIVI,
|
||||
'SHWHS' => $WHS
|
||||
];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
return response()->json([
|
||||
'code' => '206',
|
||||
'status' => 'Error',
|
||||
'message' => $responseStatusCode . '-' . $M3Errors . '- TYPE :' . $TYPE . '-' . $M3JSONResponse
|
||||
]);
|
||||
}
|
||||
}
|
||||
# A4SPR15A01 Does not Exist : Failure
|
||||
else {
|
||||
# Return Error
|
||||
return response()->json([
|
||||
'code' => '405',
|
||||
'status' => 'Error',
|
||||
'message' => 'Json Payload Not Valid, missing Parameter or no Macpicker # found.'
|
||||
]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
# Write to Logs Out : Error
|
||||
$DELIVERYNO = isset($DELIVERYNO) ? $DELIVERYNO : '000000';
|
||||
$data = ['SHMACPKR' => $DELIVERYNO,
|
||||
'SHDT' => date('Y-m-d'),
|
||||
'SHTIME' => date('H:i:s'),
|
||||
'SHERROR' => 'X',
|
||||
'SHINTBOX' => '',
|
||||
'SHTYPE' => 'M3-Res-out',
|
||||
'SHDATA' => 'No URL Parameters Sent',
|
||||
'SHUSER' => $SHUSER,
|
||||
'SHSOURCE' => $SHSOURCE,
|
||||
'SHCO' => $DIVI,
|
||||
'SHWHS' => $WHS
|
||||
];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
# Return Error
|
||||
return response()->json([
|
||||
'code' => '405',
|
||||
'status' => 'Error',
|
||||
'message' => 'No URL Parameters Sent'
|
||||
]);
|
||||
}
|
||||
} catch (\Throwable $th) {
|
||||
// Log::error($th);
|
||||
$getCurlErrors = str_contains($th->getMessage(), 'cURL error');
|
||||
if ($getCurlErrors) {
|
||||
# Write to Logs Out : Failed
|
||||
$data = ['SHMACPKR' => $DELIVERYNO,
|
||||
'SHDT' => date('Y-m-d'),
|
||||
'SHTIME' => date('H:i:s'),
|
||||
'SHERROR' => 'X',
|
||||
'SHINTBOX' => '',
|
||||
'SHTYPE' => 'M3-Res-out',
|
||||
'SHDATA' => 'Curl Error: Communication with M3 Timed Out' . ' M3-JSN-out' . $JSON,
|
||||
'SHUSER' => $SHUSER,
|
||||
'SHSOURCE' => $SHSOURCE,
|
||||
'SHCO' => $DIVI,
|
||||
'SHWHS' => $WHS
|
||||
];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
return response()->json([
|
||||
'code' => '405',
|
||||
'status' => 'error',
|
||||
'message' => 'Curl Error: Communication with M3 Timed Out.'
|
||||
]);
|
||||
} else {
|
||||
# Write to Logs Out : Error
|
||||
$DELIVERYNO = isset($DELIVERYNO) ? $DELIVERYNO : '000000';
|
||||
$data = ['SHMACPKR' => $DELIVERYNO,
|
||||
'SHDT' => date('Y-m-d'),
|
||||
'SHTIME' => date('H:i:s'),
|
||||
'SHERROR' => 'X',
|
||||
'SHINTBOX' => '',
|
||||
'SHTYPE' => 'M3-Err-out',
|
||||
'SHDATA' => 'An Error Occured - ' . substr($th, 0, 300),
|
||||
'SHUSER' => $SHUSER,
|
||||
'SHSOURCE' => $SHSOURCE,
|
||||
'SHCO' => $DIVI,
|
||||
'SHWHS' => $WHS
|
||||
];
|
||||
Helper::logToICM699M($data);
|
||||
Log::error($th);
|
||||
|
||||
return response()->json([
|
||||
'code' => '405',
|
||||
'status' => 'error',
|
||||
'message' => 'Uncaught Error'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
# End UpdateShipmentNumber
|
||||
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers\API;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use DB;
|
||||
use Config;
|
||||
use Str;
|
||||
use Log;
|
||||
use Http;
|
||||
use Cache;
|
||||
use DateTime;
|
||||
use Smalot\PdfParser\Parser;
|
||||
use File;
|
||||
use Modules\M3\Helpers\Helper;
|
||||
|
||||
class TwoShipAPIs extends Controller
|
||||
{
|
||||
# TwoShipUpdateHold with URL Params
|
||||
public function TwoShipUpdateHold(Request $request)
|
||||
{
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('max_input_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOut'));
|
||||
|
||||
// dd($request->all());
|
||||
|
||||
// Log::info( $request->all() );
|
||||
# Get The Calling User
|
||||
$SHUSER = m3_user() !== '' ? Str::upper(m3_user()) : 'WebUser';
|
||||
|
||||
$SHSOURCE = 'TwoShipUpdateHold';
|
||||
$TwoShipErrors = '';
|
||||
|
||||
$urlParams = count($request->all()) > 0 ? $request->all() : '';
|
||||
$WHS = isset($urlParams["WHS"]) ? $urlParams["WHS"] : '';
|
||||
$CO = isset($urlParams["COMPANY"]) ? $urlParams["COMPANY"] : '';
|
||||
$MACPKR = isset($urlParams["MACPKR"]) ? $urlParams["MACPKR"] : '';
|
||||
|
||||
try {
|
||||
if ($urlParams != '') {
|
||||
$IncomingParams = ['CO' => $CO, 'WHS' => $WHS, 'MACPKR' => $MACPKR];
|
||||
$IncomingParams = json_encode($IncomingParams);
|
||||
|
||||
# Write to Logs : Params In
|
||||
$data = ['SHMACPKR' => $MACPKR,
|
||||
'SHDT' => date('Y-m-d'),
|
||||
'SHTIME' => date('H:i:s'),
|
||||
'SHERROR' => '',
|
||||
'SHINTBOX' => '',
|
||||
'SHTYPE' => 'AggStopReq',
|
||||
'SHDATA' => $IncomingParams,
|
||||
'SHUSER' => $SHUSER,
|
||||
'SHSOURCE' => $SHSOURCE,
|
||||
'SHCO' => $CO,
|
||||
'SHWHS' => $WHS
|
||||
];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
# First Step : Get MACPKRs list if available
|
||||
# select a4macpkr from icm688m1 where a4shpaggcd in (select a4shpaggcd from icm688m1 where a4macpkr=233709) and a4shpaggcd<>0 and a4concmplt<>'y' and a4co=410 and a4whs=111
|
||||
$A4MACPKRSel = DB::connection(config('m3.connection', 'pgsql'))->select(
|
||||
"select a4macpkr from icm688m1 where a4shpaggcd in (select a4shpaggcd from icm688m1 where a4macpkr={$MACPKR})
|
||||
and a4shpaggcd<>0 and a4concmplt<>'y' and a4co='{$CO}' and a4whs='{$WHS}' "
|
||||
);
|
||||
// dd($A4MACPKRSel);
|
||||
|
||||
if (count($A4MACPKRSel)>0){
|
||||
foreach ($A4MACPKRSel as $key => $A4MACPKRR) {
|
||||
$A4MACPKRArr[] = $A4MACPKRR->A4MACPKR;
|
||||
}
|
||||
}
|
||||
else{
|
||||
$A4MACPKRArr[] = $MACPKR;
|
||||
}
|
||||
|
||||
// dump($A4MACPKRArr);
|
||||
|
||||
# Call 2ship API with Params
|
||||
$WS_key = Config::get('arrays.2Ship.TwoShip_Key');
|
||||
$end_point = Config::get('arrays.2Ship.end_point');
|
||||
$API = Config::get('arrays.2Ship.hold_update');
|
||||
|
||||
$ShipOnHoldOrder_url = $end_point . $API;
|
||||
|
||||
# Build Json Data
|
||||
$data = [
|
||||
'WS_Key' => $WS_key,
|
||||
'OrderNumbers' => [implode(',', $A4MACPKRArr)],
|
||||
// 'ShipmentId' => 3,
|
||||
'FindBy' => 'ByMultipleOrderNumbers',
|
||||
'DataToBeUpdated' => [
|
||||
'UpdateAggregationSettings' => true,
|
||||
'OrderAggregationSettingsInfo' => [
|
||||
'NotConsideredAggregation' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$json_string = json_encode($data);
|
||||
|
||||
// dump($json_string);
|
||||
|
||||
#######
|
||||
# Initialise the cURL var
|
||||
$ch = curl_init();
|
||||
|
||||
# Get the response from cURL
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
|
||||
|
||||
curl_setopt($ch, CURLOPT_URL, $ShipOnHoldOrder_url);
|
||||
curl_setopt($ch, CURLOPT_VERBOSE, false);
|
||||
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
#When CURLOPT_SSL_VERIFYPEER is enabled (value=1), and the verification fails to prove that the certificate is authentic, the connection fails.
|
||||
#When the option is zero, the peer certificate verification succeeds regardless.
|
||||
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
|
||||
#When CURLOPT_SSL_VERIFYHOST is 2, that certificate must indicate that the server is the server to which you meant to connect,
|
||||
#or the connection fails. Simply put, it means it has to have the same name in the certificate as is in the URL you operate against.
|
||||
|
||||
# Set data content type
|
||||
curl_setopt(
|
||||
$ch,
|
||||
CURLOPT_HTTPHEADER,
|
||||
array(
|
||||
'Content-Type: application/json',
|
||||
'Content-Length: ' . strlen($json_string)
|
||||
)
|
||||
);
|
||||
|
||||
# Post data
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $json_string);
|
||||
|
||||
# Set timeout
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, Config::get('arrays.PHPTimeOut'));
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, Config::get('arrays.PHPTimeOut'));
|
||||
|
||||
# if set true, cURL will follow redirects
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
|
||||
# Execute the request
|
||||
$response = curl_exec($ch);
|
||||
|
||||
# Verifying error
|
||||
$info = curl_getinfo($ch);
|
||||
|
||||
# Get status
|
||||
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
# Output the error code
|
||||
# $CurlError= curl_error($ch);
|
||||
$CurlError = str_replace("'", " ", curl_error($ch));
|
||||
|
||||
# Close the session
|
||||
unset($ch);
|
||||
|
||||
// dump($response);
|
||||
// dump($status);
|
||||
// dump($CurlError);
|
||||
|
||||
if ($status == '200' && $CurlError=='') {
|
||||
$responseJSON = json_decode($response);
|
||||
// dump($responseJSON);
|
||||
if($responseJSON->Success==false){
|
||||
$TwoShipErrors = '2Ship Error: '.$responseJSON->GlobalError;
|
||||
}
|
||||
} else {
|
||||
$TwoShipErrors = 'Error: No Response from 2Ship';
|
||||
$TwoShipErrors .= ' -Curl Error: '.$CurlError;
|
||||
}
|
||||
|
||||
# Validate response From 2Ship
|
||||
# Error
|
||||
if ($TwoShipErrors != '') {
|
||||
// dump($TwoShipErrors);
|
||||
|
||||
# Write to Logs : Error
|
||||
$data = ['SHMACPKR' => $MACPKR,
|
||||
'SHDT' => date('Y-m-d'),
|
||||
'SHTIME' => date('H:i:s'),
|
||||
'SHERROR' => 'X',
|
||||
'SHINTBOX' => '',
|
||||
'SHTYPE' => 'AggStopRsp',
|
||||
'SHDATA' => $status . '-' . $TwoShipErrors,
|
||||
'SHUSER' => $SHUSER,
|
||||
'SHSOURCE' => $SHSOURCE,
|
||||
'SHCO' => $CO,
|
||||
'SHWHS' => $WHS
|
||||
];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
# Send Response
|
||||
return response()->json([
|
||||
'code' => '405',
|
||||
'status' => 'error',
|
||||
'message' => 'Status: '.$status . '-' . $TwoShipErrors
|
||||
]);
|
||||
}
|
||||
# Success
|
||||
else{
|
||||
# Write to Logs : JSON
|
||||
$data = ['SHMACPKR' => $MACPKR,
|
||||
'SHDT' => date('Y-m-d'),
|
||||
'SHTIME' => date('H:i:s'),
|
||||
'SHERROR' => '',
|
||||
'SHINTBOX' => '',
|
||||
'SHTYPE' => 'AggStopRsp',
|
||||
'SHDATA' => $response,
|
||||
'SHUSER' => $SHUSER,
|
||||
'SHSOURCE' => $SHSOURCE,
|
||||
'SHCO' => $CO,
|
||||
'SHWHS' => $WHS
|
||||
];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
# Update ICM688M1 set a4concmplt to 'y'
|
||||
DB::connection(config('m3.connection', 'pgsql'))->table('icm688m1')
|
||||
->whereIn('A4MACPKR',$A4MACPKRArr)
|
||||
->where('A4CO',$CO)
|
||||
->where('A4WHS',$WHS)
|
||||
->update(['A4CONCMPLT'=>'Y']);
|
||||
|
||||
}
|
||||
# Send Response
|
||||
return response()->json([
|
||||
'code' => '200',
|
||||
'status' => 'Success'
|
||||
]);
|
||||
}
|
||||
# Error : No URL params
|
||||
else {
|
||||
# Write to Logs Out : Error
|
||||
$MACPKR = isset($MACPKR) ? $MACPKR : '000000';
|
||||
$data = ['SHMACPKR' => $MACPKR,
|
||||
'SHDT' => date('Y-m-d'),
|
||||
'SHTIME' => date('H:i:s'),
|
||||
'SHERROR' => 'X',
|
||||
'SHINTBOX' => '',
|
||||
'SHTYPE' => 'AggStopRsp',
|
||||
'SHDATA' => 'No URL Parameters Sent',
|
||||
'SHUSER' => $SHUSER,
|
||||
'SHSOURCE' => $SHSOURCE,
|
||||
'SHCO' => $CO,
|
||||
'SHWHS' => $WHS
|
||||
];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
# Return Error
|
||||
return response()->json([
|
||||
'code' => '405',
|
||||
'status' => 'Error',
|
||||
'message' => 'No URL Parameters Sent'
|
||||
]);
|
||||
}
|
||||
} catch (\Throwable $th) {
|
||||
# Write to Logs Out : Error
|
||||
$getCurlErrors = str_contains($th->getMessage(), 'cURL error');
|
||||
if ($getCurlErrors) {
|
||||
// dd($getCurlErrors);
|
||||
# Write to Logs Out : Failed
|
||||
$data = ['SHMACPKR' => $MACPKR,
|
||||
'SHDT' => date('Y-m-d'),
|
||||
'SHTIME' => date('H:i:s'),
|
||||
'SHERROR' => 'X',
|
||||
'SHINTBOX' => '',
|
||||
'SHTYPE' => 'AggStopRsp',
|
||||
'SHDATA' => 'Curl Error: Communication with 2Ship Timed Out' . ' 2Ship-JSN-out' . $IncomingParams,
|
||||
'SHUSER' => $SHUSER,
|
||||
'SHSOURCE' => $SHSOURCE,
|
||||
'SHCO' => $CO,
|
||||
'SHWHS' => $WHS
|
||||
];
|
||||
Helper::logToICM699M($data);
|
||||
|
||||
return response()->json([
|
||||
'code' => '405',
|
||||
'status' => 'error',
|
||||
'message' => 'Curl Error: Communication with 2Ship Timed Out.'
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
# End TwoShipUpdateHold
|
||||
}
|
||||
@@ -0,0 +1,314 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use DB;
|
||||
use Config;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Str;
|
||||
|
||||
class BoxPackToPalletController extends Controller
|
||||
{
|
||||
|
||||
public static function index(Request $request)
|
||||
{
|
||||
return view('m3::liberty-theme.pages.BoxPackToPallet');
|
||||
}
|
||||
|
||||
# Load Existing Boxes from ICM659M
|
||||
public static function getBoxes(Request $request)
|
||||
{
|
||||
$R659PALT = $request->R659PALT ?? abort(404, 'Manifest Not Found');
|
||||
|
||||
$userWhsCoPlant = self::getUserWhsCoPlant();
|
||||
// dump($userWhsCoPlant);
|
||||
|
||||
$boxes = DB::connection(config('m3.connection', 'pgsql'))->table('ICM659M as p')
|
||||
->select(
|
||||
'p.R659PALT',
|
||||
'p.R659BOX',
|
||||
'p.R659LOADED',
|
||||
'p.R659USER',
|
||||
'p.R659DATE',
|
||||
'p.R659TIME',
|
||||
'c.AYMACPKR',
|
||||
'c.AYSPR15A01',
|
||||
'cv.A4APR8N001',
|
||||
'cv.A4SHSHCT',
|
||||
'cnv.R652SORTK as CONVEYOR_NAME'
|
||||
)
|
||||
->leftJoin('ICM695M1 as c', 'p.R659BOX', '=', 'c.AYINTBOX')
|
||||
->leftJoin('ICM688M1 as cv', 'c.AYMACPKR', '=', 'cv.A4MACPKR')
|
||||
->leftJoin('ICM652M as cnv', 'cv.A4APR8N001', '=', 'cnv.R652SEQ')
|
||||
->where('p.R659PALT', $R659PALT)
|
||||
->where('p.R659CO', trim($userWhsCoPlant["USERCO"]))
|
||||
->where('p.R659WHS', trim($userWhsCoPlant["USERWHS"]))
|
||||
->where('p.R659PLANT', trim($userWhsCoPlant["USERPL"]))
|
||||
->orderBy('p.R659DATE', 'desc')
|
||||
->orderBy('p.R659TIME', 'desc')
|
||||
->distinct()
|
||||
->get()
|
||||
->unique('R659BOX')
|
||||
->values();
|
||||
// dump($boxes);
|
||||
|
||||
if ($request->ajax()) {
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $boxes,
|
||||
]);
|
||||
}
|
||||
|
||||
$palletHeader = $boxes->first();
|
||||
// dump($boxes);
|
||||
|
||||
return view('m3::liberty-theme.pages.BoxPackToPalletScan', compact('boxes', 'palletHeader', 'R659PALT'));
|
||||
}
|
||||
|
||||
# Scan Boxes
|
||||
public static function scanBoxes(Request $request)
|
||||
{
|
||||
$R659PALT = $request->R659PALT ?? abort(400, 'Pallet Not Found');
|
||||
$R659BOX = trim($request->R659BOX) ?? abort(400, 'Box Not Found');
|
||||
$SHUSER = m3_user() !== '' ? Str::upper(m3_user()) : 'WebUser';
|
||||
$userWhsCoPlant = self::getUserWhsCoPlant();
|
||||
|
||||
$boxMessage = '';
|
||||
|
||||
# Step 1: Check for duplicate — same pallet + box combo
|
||||
$exists = DB::connection(config('m3.connection', 'pgsql'))
|
||||
->table('icm659m')
|
||||
->select('R659PALT')
|
||||
->where('R659PALT', $R659PALT)
|
||||
->where('R659BOX', $R659BOX)
|
||||
->where('R659CO', trim($userWhsCoPlant["USERCO"]))
|
||||
->where('R659WHS', trim($userWhsCoPlant["USERWHS"]))
|
||||
->where('R659PLANT', trim($userWhsCoPlant["USERPL"]))
|
||||
->first();
|
||||
|
||||
if ($exists) {
|
||||
$boxMessage = "• Box {$R659BOX} is already assigned to Pallet {$exists->R659PALT}.";
|
||||
}
|
||||
|
||||
# Step 2: Check if Box exists in ICM695M1 (with carrier + conveyor joined)
|
||||
$ICM695M1Sel = DB::connection(config('m3.connection', 'pgsql'))
|
||||
->table('ICM695M1 as c')
|
||||
->select(
|
||||
'c.AYINTBOX',
|
||||
'c.AYSPR15A01',
|
||||
'c.AYTYPE',
|
||||
'c.AYMACPKR',
|
||||
'cv.A4APR8N001',
|
||||
'cnv.R652SORTK as CONVEYOR_NAME'
|
||||
)
|
||||
->leftJoin('ICM688M1 as cv', 'c.AYMACPKR', '=', 'cv.A4MACPKR')
|
||||
->leftJoin('ICM652M as cnv', 'cv.A4APR8N001', '=', 'cnv.R652SEQ')
|
||||
->where('c.AYINTBOX', $R659BOX)
|
||||
->where('c.AYCO', trim($userWhsCoPlant["USERCO"]))
|
||||
->where('c.AYWHS', trim($userWhsCoPlant["USERWHS"]))
|
||||
->where('c.AYPLANT', trim($userWhsCoPlant["USERPL"]))
|
||||
->first();
|
||||
|
||||
$boxExistInICM695M = isset($ICM695M1Sel->AYINTBOX);
|
||||
$boxisPalletICM695M = isset($ICM695M1Sel->AYTYPE) && $ICM695M1Sel->AYTYPE != 'BX';
|
||||
|
||||
if (!$boxExistInICM695M) {
|
||||
$br = $boxMessage == '' ? '' : '<br>';
|
||||
$boxMessage .= $br . "• Box {$R659BOX} does not exist in ICM695M1 or it belongs to another Company.";
|
||||
}
|
||||
|
||||
if ($boxExistInICM695M && $boxisPalletICM695M) {
|
||||
$br = $boxMessage == '' ? '' : '<br>';
|
||||
$boxMessage .= $br . "• Scanned barcode {$R659BOX} is not a Box.";
|
||||
}
|
||||
|
||||
# Step 3: Check that all boxes on the pallet share the same Carrier and Conveyor
|
||||
if ($boxExistInICM695M && !$boxisPalletICM695M && !$exists) {
|
||||
$firstPalletBox = DB::connection(config('m3.connection', 'pgsql'))
|
||||
->table('ICM659M as p')
|
||||
->select(
|
||||
'c.AYSPR15A01',
|
||||
'cnv.R652SORTK as CONVEYOR_NAME'
|
||||
)
|
||||
->leftJoin('ICM695M1 as c', 'p.R659BOX', '=', 'c.AYINTBOX')
|
||||
->leftJoin('ICM688M1 as cv', 'c.AYMACPKR', '=', 'cv.A4MACPKR')
|
||||
->leftJoin('ICM652M as cnv', 'cv.A4APR8N001', '=', 'cnv.R652SEQ')
|
||||
->where('p.R659PALT', $R659PALT)
|
||||
->where('p.R659CO', trim($userWhsCoPlant["USERCO"]))
|
||||
->where('p.R659WHS', trim($userWhsCoPlant["USERWHS"]))
|
||||
->where('p.R659PLANT', trim($userWhsCoPlant["USERPL"]))
|
||||
->first();
|
||||
|
||||
if ($firstPalletBox) {
|
||||
$incomingCarrier = trim($ICM695M1Sel->AYSPR15A01 ?? '');
|
||||
$incomingConveyor = trim($ICM695M1Sel->CONVEYOR_NAME ?? '');
|
||||
$palletCarrier = trim($firstPalletBox->AYSPR15A01 ?? '');
|
||||
$palletConveyor = trim($firstPalletBox->CONVEYOR_NAME ?? '');
|
||||
|
||||
if ($incomingCarrier !== $palletCarrier) {
|
||||
$br = $boxMessage == '' ? '' : '<br>';
|
||||
$boxMessage .= $br . "• Box {$R659BOX} has a different Carrier ({$incomingCarrier}) than the boxes already on Pallet {$R659PALT} ({$palletCarrier}).";
|
||||
}
|
||||
|
||||
if ($incomingConveyor !== $palletConveyor) {
|
||||
$br = $boxMessage == '' ? '' : '<br>';
|
||||
$boxMessage .= $br . "• Box {$R659BOX} has a different Conveyor ({$incomingConveyor}) than the boxes already on Pallet {$R659PALT} ({$palletConveyor}).";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($exists || !$boxExistInICM695M || $boxisPalletICM695M || $boxMessage !== '') {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => $boxMessage,
|
||||
], 409);
|
||||
}
|
||||
|
||||
# Step 4: Insert new box record
|
||||
DB::connection(config('m3.connection', 'pgsql'))
|
||||
->table('icm659m')
|
||||
->insert([
|
||||
'R659PALT' => $R659PALT,
|
||||
'R659BOX' => $R659BOX,
|
||||
'R659LOADED' => '',
|
||||
'R659USER' => $SHUSER,
|
||||
'R659DATE' => date('Y-m-d'),
|
||||
'R659TIME' => date('H:i:s'),
|
||||
'R659CO' => trim($userWhsCoPlant["USERCO"]),
|
||||
'R659WHS' => trim($userWhsCoPlant["USERWHS"]),
|
||||
'R659PLANT' => trim($userWhsCoPlant["USERPL"]),
|
||||
]);
|
||||
|
||||
# Step 5: Return the full refreshed box list
|
||||
$boxes = DB::connection(config('m3.connection', 'pgsql'))->table('ICM659M as p')
|
||||
->select(
|
||||
'p.R659PALT',
|
||||
'p.R659BOX',
|
||||
'p.R659LOADED',
|
||||
'p.R659USER',
|
||||
'p.R659DATE',
|
||||
'p.R659TIME',
|
||||
'c.AYMACPKR',
|
||||
'c.AYSPR15A01',
|
||||
'cv.A4APR8N001',
|
||||
'cv.A4SHSHCT',
|
||||
'cnv.R652SORTK as CONVEYOR_NAME'
|
||||
)
|
||||
->leftJoin('ICM695M1 as c', 'p.R659BOX', '=', 'c.AYINTBOX')
|
||||
->leftJoin('ICM688M1 as cv', 'c.AYMACPKR', '=', 'cv.A4MACPKR')
|
||||
->leftJoin('ICM652M as cnv', 'cv.A4APR8N001', '=', 'cnv.R652SEQ')
|
||||
->where('p.R659PALT', $R659PALT)
|
||||
->where('p.R659CO', trim($userWhsCoPlant["USERCO"]))
|
||||
->where('p.R659WHS', trim($userWhsCoPlant["USERWHS"]))
|
||||
->where('p.R659PLANT', trim($userWhsCoPlant["USERPL"]))
|
||||
->orderBy('p.R659DATE', 'desc')
|
||||
->orderBy('p.R659TIME', 'desc')
|
||||
->distinct()
|
||||
->get()
|
||||
->unique('R659BOX')
|
||||
->values();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => "• Box {$R659BOX} added to Pallet {$R659PALT}.",
|
||||
'data' => $boxes,
|
||||
]);
|
||||
}
|
||||
|
||||
# Delete Box
|
||||
public static function deleteBox(Request $request)
|
||||
{
|
||||
$R659PALT = $request->R659PALT ?? abort(400, 'Pallet Not Found');
|
||||
$R659BOX = trim($request->R659BOX) ?? abort(400, 'Box Not Found');
|
||||
|
||||
$userWhsCoPlant = self::getUserWhsCoPlant();
|
||||
|
||||
# Guard: only allow delete if R659LOADED is empty
|
||||
$record = DB::connection(config('m3.connection', 'pgsql'))
|
||||
->table('icm659m')
|
||||
->where('R659PALT', $R659PALT)
|
||||
->where('R659BOX', $R659BOX)
|
||||
->first();
|
||||
|
||||
if (!$record) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => "Box {$R659BOX} not found on Pallet {$R659PALT}.",
|
||||
], 404);
|
||||
}
|
||||
|
||||
if (!empty(trim($record->R659LOADED))) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => "Box {$R659BOX} is already loaded and cannot be removed.",
|
||||
], 403);
|
||||
}
|
||||
|
||||
DB::connection(config('m3.connection', 'pgsql'))
|
||||
->table('icm659m')
|
||||
->where('R659PALT', $R659PALT)
|
||||
->where('R659BOX', $R659BOX)
|
||||
->delete();
|
||||
|
||||
# Return refreshed list
|
||||
$boxes = DB::connection(config('m3.connection', 'pgsql'))->table('ICM659M as p')
|
||||
->select(
|
||||
'p.R659PALT',
|
||||
'p.R659BOX',
|
||||
'p.R659LOADED',
|
||||
'p.R659USER',
|
||||
'p.R659DATE',
|
||||
'p.R659TIME',
|
||||
'c.AYMACPKR',
|
||||
'c.AYSPR15A01',
|
||||
'cv.A4APR8N001',
|
||||
'cv.A4SHSHCT',
|
||||
'cnv.R652SORTK as CONVEYOR_NAME'
|
||||
)
|
||||
->leftJoin('ICM695M1 as c', 'p.R659BOX', '=', 'c.AYINTBOX')
|
||||
->leftJoin('ICM688M1 as cv', 'c.AYMACPKR', '=', 'cv.A4MACPKR')
|
||||
->leftJoin('ICM652M as cnv', 'cv.A4APR8N001', '=', 'cnv.R652SEQ')
|
||||
->where('p.R659PALT', $R659PALT)
|
||||
->where('p.R659CO', trim($userWhsCoPlant["USERCO"]))
|
||||
->where('p.R659WHS', trim($userWhsCoPlant["USERWHS"]))
|
||||
->where('p.R659PLANT', trim($userWhsCoPlant["USERPL"]))
|
||||
->orderBy('p.R659DATE', 'desc')
|
||||
->orderBy('p.R659TIME', 'desc')
|
||||
->distinct()
|
||||
->get()
|
||||
->unique('R659BOX')
|
||||
->values();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => "Box {$R659BOX} removed from Pallet {$R659PALT}.",
|
||||
'data' => $boxes,
|
||||
]);
|
||||
}
|
||||
|
||||
# Get Logged User CO/WHS/PLANT
|
||||
public static function getUserWhsCoPlant()
|
||||
{
|
||||
$SHUSER = m3_user() !== '' ? Str::upper(trim(m3_user())) : '';
|
||||
# Get users from ICM428M
|
||||
$ICM428M = DB::connection(config('m3.connection', 'pgsql'))->table('icm428m')
|
||||
->select('R428US', 'R428CO', 'R428WH', 'R428PL')
|
||||
->where('R428US', '=', $SHUSER)
|
||||
->first();
|
||||
|
||||
$R428US = isset($ICM428M->R428US) ? $ICM428M->R428US : '';
|
||||
$USERCO = isset($ICM428M->R428CO) ? $ICM428M->R428CO : '';
|
||||
$USERWH = isset($ICM428M->R428WH) ? $ICM428M->R428WH : '';
|
||||
$R428PL = isset($ICM428M->R428PL) ? $ICM428M->R428PL : '';
|
||||
|
||||
$userWhsCoPlant = [
|
||||
"R428US" => $R428US,
|
||||
"USERCO" => $USERCO,
|
||||
"USERWHS" => $USERWH,
|
||||
"USERPL" => $R428PL,
|
||||
];
|
||||
return $userWhsCoPlant;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers;
|
||||
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
|
||||
class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
|
||||
}
|
||||
@@ -0,0 +1,302 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use DB;
|
||||
use Config;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
// use Modules\M3\Models\ICM709M;
|
||||
//
|
||||
|
||||
class GetContentsController extends Controller
|
||||
{
|
||||
|
||||
public function processShipment(Request $request)
|
||||
{
|
||||
# Get Mackpkr from Request
|
||||
$macpacPicker = isset($request->MACPKR) ? trim($request->MACPKR) : '';
|
||||
|
||||
# ESN1
|
||||
# $macpacPicker='888568'; // LTL example
|
||||
# $macpacPicker='894337'; // another LTL example with smaller orders, therefore pallets are more mixed
|
||||
# $macpacPicker='1225311'; // parcel example
|
||||
# ESN2
|
||||
# $macpacPicker='748101'; // LTL example
|
||||
|
||||
try {
|
||||
$icm704mArray = $this->buildNMFCCodesArray();
|
||||
|
||||
$shipmentData = $this->getShipmentData($macpacPicker);
|
||||
if (empty($shipmentData['orderNumber'])) {
|
||||
return response()->json(['error' => "Picker {$macpacPicker} was not found in ICM688M1"]);
|
||||
}
|
||||
|
||||
# Get Packages
|
||||
$packages = $this->getPackagesData($shipmentData['macpkr_list']);
|
||||
# Add NMFC to Packages
|
||||
$packagesWithNMFC = $this->addNMFCDataToPackages($packages, $macpacPicker, $icm704mArray);
|
||||
|
||||
# Get Commodities
|
||||
$commodities = $this->getCommoditiesData(
|
||||
$shipmentData['company'],
|
||||
$shipmentData['warehouse'],
|
||||
$macpacPicker,
|
||||
$packages['package_595m1'],
|
||||
$icm704mArray
|
||||
);
|
||||
|
||||
return response()->json([
|
||||
'error' => '',
|
||||
'shipmentData' => $shipmentData,
|
||||
'packages' => $packagesWithNMFC,
|
||||
'commodities' => $commodities
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return response()->json(['error' => $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
|
||||
protected function buildNMFCCodesArray()
|
||||
{
|
||||
$results = DB::table('ICM704M')->get();
|
||||
|
||||
return $results->mapWithKeys(function ($row) {
|
||||
// dump($row);
|
||||
return [
|
||||
trim($row->AONMIT) => [
|
||||
'LTLClassId' => number_format(trim($row->AOFCID), 1),
|
||||
'NMFCItem' => trim($row->AONMIT),
|
||||
'NMFCSub' => trim($row->AONMSB),
|
||||
'SkidDescription' => trim($row->AOSKDE)
|
||||
]
|
||||
];
|
||||
})->all();
|
||||
|
||||
}
|
||||
|
||||
protected function getShipmentData($macpacPicker)
|
||||
{
|
||||
$result = DB::select("
|
||||
SELECT
|
||||
SUM(A4TPCKWGHT) as total_weight,
|
||||
A4MACPKR, A4SHSHA1, A4SHSHA2, A4SHSHCI, A4SHSHNM,
|
||||
A4SHSHCT, A4SHSHZP, A4SHSHST, A4ONO, A4STCN, A4CO,
|
||||
A4WHS, A4SHIPVIA, A4SLCO, A4SLWHS, A4CATPID, A42SSVCCOD,
|
||||
A4CARRIER, A4SHPAGGCD, A4SALESLOC, A4SHCSPO, A4OFSTRM,
|
||||
A4SCAC, A4PLANT
|
||||
FROM ICM688M1
|
||||
WHERE A4MACPKR = ?
|
||||
GROUP BY A4MACPKR, A4SHSHA1, A4SHSHA2, A4SHSHCI, A4SHSHNM,
|
||||
A4SHSHCT, A4SHSHZP, A4SHSHST, A4ONO, A4RLNO, A4SHNO,
|
||||
A4STCN, A4CO, A4WHS, A4SHIPVIA, A4SLCO, A4SLWHS,
|
||||
A4CATPID, A42SSVCCOD, A4CARRIER, A4SHPAGGCD,
|
||||
A4SALESLOC, A4SHCSPO, A4OFSTRM, A4SCAC, A4PLANT",
|
||||
[$macpacPicker]
|
||||
);
|
||||
|
||||
if (empty($result)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$row = $result[0];
|
||||
$aggCode = trim($row->A4SHPAGGCD);
|
||||
|
||||
return [
|
||||
'orderNumber' => trim($row->A4MACPKR),
|
||||
'recipient' => [
|
||||
'address1' => trim($row->A4SHSHA1),
|
||||
'address2' => trim($row->A4SHSHA2),
|
||||
'city' => trim($row->A4SHSHCI),
|
||||
'companyName' => trim($row->A4SHSHNM),
|
||||
'country' => trim($row->A4SHSHCT),
|
||||
'postalCode' => trim($row->A4SHSHZP),
|
||||
'state' => trim($row->A4SHSHST),
|
||||
],
|
||||
'shipmentReference' => trim($row->A4ONO),
|
||||
'company' => trim($row->A4CO),
|
||||
'warehouse' => trim($row->A4WHS),
|
||||
'macpkr_list' => $macpacPicker,
|
||||
'shipment_list' => "'" . trim($row->A4ONO) . "'",
|
||||
'po_list' => "'" . trim($row->A4SHCSPO) . "'",
|
||||
'order_list' => "'" . trim($row->A4ONO) . "'"
|
||||
];
|
||||
}
|
||||
|
||||
protected function getPackagesData($macpkrList)
|
||||
{
|
||||
$results = DB::select("
|
||||
SELECT
|
||||
AYINTBOX,
|
||||
MAX(AYHEIGHT) as height,
|
||||
MAX(AYWIDTH) as width,
|
||||
MAX(AYDEPTH) as depth,
|
||||
SUM(AYLNWGHT) as weight
|
||||
FROM ICM695M1
|
||||
WHERE AYMACPKR IN (?)
|
||||
GROUP BY AYINTBOX
|
||||
ORDER BY AYINTBOX",
|
||||
[$macpkrList]
|
||||
);
|
||||
|
||||
$packages = [];
|
||||
$package595m1 = [];
|
||||
$packagesGS1Array = [];
|
||||
|
||||
foreach ($results as $index => $row) {
|
||||
// dump($row);
|
||||
$internalBox = trim($row->AYINTBOX);
|
||||
|
||||
$package595m1[$internalBox] = [
|
||||
'INDEX' => $index,
|
||||
'HEIGHT' => $row->HEIGHT,
|
||||
'WIDTH' => $row->WIDTH,
|
||||
'DEPTH' => $row->DEPTH,
|
||||
'WEIGHT' => $row->WEIGHT
|
||||
];
|
||||
|
||||
$packages[] = [
|
||||
'Width' => $row->WIDTH,
|
||||
'Height' => $row->HEIGHT,
|
||||
'Length' => $row->DEPTH,
|
||||
'Weight' => $row->WEIGHT,
|
||||
'LicencePlate' => $internalBox,
|
||||
'Reference1' => $internalBox,
|
||||
'WeightType' => 0,
|
||||
'DimensionType' => 0
|
||||
];
|
||||
|
||||
$packagesGS1Array[] = $internalBox;
|
||||
}
|
||||
|
||||
return [
|
||||
'packages' => $packages,
|
||||
'package_595m1' => $package595m1,
|
||||
'packagesGS1Array' => $packagesGS1Array
|
||||
];
|
||||
}
|
||||
|
||||
protected function addNMFCDataToPackages($packages, $macpkrList, $icm704mArray)
|
||||
{
|
||||
$nmfcResults = DB::select("
|
||||
WITH tempfile AS (
|
||||
SELECT
|
||||
(SELECT A5WBFRCT FROM ICM688M2
|
||||
WHERE A5MACPKR IN (?) AND A5PART=AZPART
|
||||
FETCH FIRST 1 ROWS ONLY) as WBFRCT,
|
||||
az.*
|
||||
FROM ICM695M2 az
|
||||
WHERE AZMACPKR IN (?)
|
||||
)
|
||||
SELECT azintbox, MIN(WBFRCT) as MIN_WBFRCT
|
||||
FROM tempfile
|
||||
GROUP BY azintbox
|
||||
ORDER BY 1",
|
||||
[$macpkrList, $macpkrList]
|
||||
);
|
||||
|
||||
foreach ($nmfcResults as $index => $row) {
|
||||
$wbfrct = trim($row->MIN_WBFRCT);
|
||||
$packages['packages'][$index]['SkidDesc'] =
|
||||
$icm704mArray[$wbfrct]['SkidDescription'] ?? 'CLIPS, FASTENERS OR MOUNTS';
|
||||
}
|
||||
|
||||
return $packages;
|
||||
}
|
||||
|
||||
protected function getCommoditiesData($company, $warehouse, $macpkrList, $package595m1, $icm704mArray)
|
||||
{
|
||||
$results = DB::select("
|
||||
WITH tempfile1 AS (
|
||||
SELECT
|
||||
A5PART,
|
||||
MAX(A5CMDESC) as A5CMDESC,
|
||||
MAX(A5MUTMS) as A5MUTMS,
|
||||
MAX(A5PMPWHT) as A5PMPWHT,
|
||||
MAX(A5SLUNPR) as A5SLUNPR,
|
||||
TRIM(MIN(A5WBFRCT)) as A5WBFRCT
|
||||
FROM ICM688M2
|
||||
WHERE A5CO = ? AND A5WHS = ? AND A5MACPKR IN (?) AND A5PACKED > 0
|
||||
GROUP BY A5PART
|
||||
),
|
||||
tempfile2 AS (
|
||||
SELECT
|
||||
AZINTBOX,
|
||||
AZPART,
|
||||
SUM(AZPACKED) as AZPACKED,
|
||||
MAX(SUBSTR(AZSPR15A01,1,4)) as HAZARDOUS
|
||||
FROM ICM695M2
|
||||
WHERE AZCO = ? AND AZWHS = ? AND AZMACPKR IN (?) AND AZPACKED <> 0
|
||||
GROUP BY AZINTBOX, AZPART
|
||||
)
|
||||
SELECT
|
||||
A5PART, A5CMDESC, A5MUTMS,
|
||||
A5PMPWHT * AZPACKED as WEIGHt,
|
||||
AZPACKED, AZINTBOX,
|
||||
A5WBFRCT, HAZARDOUS, A5SLUNPR
|
||||
FROM tempfile1
|
||||
LEFT JOIN tempfile2 ON AZPART = A5PART
|
||||
ORDER BY A5PART",
|
||||
[$company, $warehouse, $macpkrList, $company, $warehouse, $macpkrList]
|
||||
);
|
||||
|
||||
$commodities = [];
|
||||
$prevPartNumber = '';
|
||||
$index = -1;
|
||||
|
||||
foreach ($results as $row) {
|
||||
$partNumber = trim($row->A5PART);
|
||||
|
||||
if ($partNumber !== $prevPartNumber) {
|
||||
$index++;
|
||||
$quantityIndex = 0;
|
||||
|
||||
$wbfrct = trim($row->A5WBFRCT);
|
||||
$nmfcData = $icm704mArray[$wbfrct] ?? [
|
||||
'LTLClassId' => '50',
|
||||
'NMFCItem' => '93490',
|
||||
'NMFCSub' => ''
|
||||
];
|
||||
|
||||
$commodities[] = [
|
||||
'Description' => trim($row->A5CMDESC),
|
||||
'PartNumber' => $partNumber,
|
||||
'SKUOrItemOrUPC' => $partNumber,
|
||||
'MadeInCountryCode' => 'US',
|
||||
'UnitValue' => $row->A5SLUNPR == '.000' ? 1 : (float) $row->A5SLUNPR,
|
||||
'TotalWeight' => (float) $row->WEIGHT,
|
||||
'QuantityUnitOfMeasure' => trim($row->A5MUTMS) ?: 'EA',
|
||||
'Quantity' => (float) $row->AZPACKED,
|
||||
'LTLClassId' => $nmfcData['LTLClassId'],
|
||||
'NMFCItem' => $nmfcData['NMFCItem'],
|
||||
'NMFCSub' => $nmfcData['NMFCSub'],
|
||||
'DangerousGoodsInfo' => [
|
||||
'ContainsDangerousGoods' => trim($row->HAZARDOUS) === 'H4.1'
|
||||
],
|
||||
'QuantityAssignment' => [
|
||||
[
|
||||
'PackageIndex' => $package595m1[trim($row->AZINTBOX)]['INDEX'],
|
||||
'Quantity' => (float) $row->AZPACKED
|
||||
]
|
||||
]
|
||||
];
|
||||
} else {
|
||||
$quantityIndex++;
|
||||
$commodities[$index]['TotalWeight'] += (float) $row->WEIGHT;
|
||||
$commodities[$index]['Quantity'] += (float) $row->AZPACKED;
|
||||
$commodities[$index]['QuantityAssignment'][] = [
|
||||
'PackageIndex' => $package595m1[trim($row->AZINTBOX)]['INDEX'],
|
||||
'Quantity' => (float) $row->AZPACKED
|
||||
];
|
||||
}
|
||||
|
||||
$prevPartNumber = $partNumber;
|
||||
}
|
||||
|
||||
return $commodities;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use DB;
|
||||
use Config;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Log;
|
||||
use Str;
|
||||
use Artisan;
|
||||
|
||||
use Modules\M3\Http\Controllers\API\CloseShipment;
|
||||
|
||||
class M3CallCloseAPIController extends Controller
|
||||
{
|
||||
public static function index(Request $request){
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('max_input_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOut'));
|
||||
|
||||
try {
|
||||
|
||||
# Get the Calling User
|
||||
# Get URL PARAMS
|
||||
$urlParams = count($request->all())>0 ? $request->all() : '';
|
||||
// dd($urlParams);
|
||||
$SHUSER = isset($urlParams["SHUSER"]) ? $urlParams["SHUSER"] : '';
|
||||
$MANIFEST = isset($urlParams["MANIFEST"]) ? $urlParams["MANIFEST"] : '';
|
||||
$APCO = isset($urlParams["APCO"]) ? $urlParams["APCO"] : '';
|
||||
$APWHS = isset($urlParams["APWHS"]) ? $urlParams["APWHS"] : '';
|
||||
|
||||
if ($MANIFEST!='' && $APCO!='' && $APWHS!='') { // $SHUSER!='' &&
|
||||
// Log::channel('dailyCron')->info("Cron...Start CallCloseAPI...For user:".$SHUSER." Manifest#: ".$MANIFEST);
|
||||
|
||||
# Get Logged User CO & WH
|
||||
# Get users from ICM428M
|
||||
// $ICM428M = DB::connection(config('m3.connection', 'pgsql'))->table('icm428m')
|
||||
// ->select('R428US','R428CO', 'R428WH')
|
||||
// ->where('R428US','=',$SHUSER)
|
||||
// ->first();
|
||||
|
||||
// $R428US = isset($ICM428M->R428US) ? $ICM428M->R428US : '';
|
||||
// $USERCO = isset($ICM428M->R428CO) ? $ICM428M->R428CO : '';
|
||||
// $USERWH = isset($ICM428M->R428WH) ? $ICM428M->R428WH : '';
|
||||
// dump($R428US.':'.$USERCO.':'.$USERWH);
|
||||
|
||||
# Get Macpickers from ICM705M1
|
||||
# SELECT APMANIFEST FROM ICM705M1 WHERE APSPARE2='' AND APCO='110' AND APWHS='321'
|
||||
$ICM705M1 = DB::connection(config('m3.connection', 'pgsql'))->table('icm705m1')
|
||||
->select('APMANIFEST','APCO','APWHS')
|
||||
->where('APSPARE2','')
|
||||
->where('APCO',$APCO)
|
||||
->where('APWHS',$APWHS)
|
||||
->where('APMANIFEST','=',$MANIFEST)
|
||||
->whereRaw('EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - APLDCLOZ)) / 60 > 15')
|
||||
->orderBy('APMANIFEST')
|
||||
->get();
|
||||
// dump($ICM705M1);
|
||||
|
||||
if (count($ICM705M1)>0) {
|
||||
# Loop the Results from $ICM705M1
|
||||
foreach ($ICM705M1 as $key => $ICM705M1R) {
|
||||
# Send CO and WHS to CallCloseAPI
|
||||
$USERCO = isset($ICM705M1R->APCO) ? $ICM705M1R->APCO : '';
|
||||
$USERWH = isset($ICM705M1R->APWHS) ? $ICM705M1R->APWHS : '';
|
||||
|
||||
$callCloseShipment = Artisan::call('command:CallCloseAPI', ['user'=> $SHUSER ,'manifest' => $ICM705M1R->APMANIFEST ,
|
||||
'co' => $USERCO ,'whs' => $USERWH]);
|
||||
// dump($callCloseShipment);
|
||||
|
||||
if ($callCloseShipment==1) {
|
||||
return response()->json([
|
||||
'code' => '200',
|
||||
'status' => 'Success',
|
||||
'message'=> 'Manifest Closing submitted'
|
||||
]);
|
||||
}
|
||||
else{
|
||||
return response()->json([
|
||||
'code' => '206',
|
||||
'status' => 'Failure',
|
||||
'message'=> 'Manifest Closing Failed'
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
Log::channel('dailyCron')->info("Manifest CloseAPI: No records found in ICM705M1...");
|
||||
return response()->json([
|
||||
'code' => '206',
|
||||
'status' => 'Error',
|
||||
'message'=> "Manifest CloseAPI: No records found in ICM705M1..."
|
||||
]);
|
||||
}
|
||||
}
|
||||
else{
|
||||
Log::channel('dailyCron')->error('Manifest CloseAPI: A User and Manifest must be defined...');
|
||||
|
||||
return response()->json([
|
||||
'code' => '206',
|
||||
'status' => 'Error',
|
||||
'message'=> 'Manifest CloseAPI: A User and Manifest must be defined...'
|
||||
]);
|
||||
}
|
||||
}
|
||||
catch (\Throwable $th) {
|
||||
Log::error($th);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,6 +10,7 @@ class M3Controller extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return Renderable
|
||||
*/
|
||||
public function index()
|
||||
@@ -19,6 +20,7 @@ class M3Controller extends Controller
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return Renderable
|
||||
*/
|
||||
public function create()
|
||||
@@ -28,7 +30,9 @@ class M3Controller extends Controller
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return Renderable
|
||||
*/
|
||||
public function store(Request $request)
|
||||
@@ -38,7 +42,9 @@ class M3Controller extends Controller
|
||||
|
||||
/**
|
||||
* Show the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return Renderable
|
||||
*/
|
||||
public function show($id)
|
||||
@@ -48,7 +54,9 @@ class M3Controller extends Controller
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return Renderable
|
||||
*/
|
||||
public function edit($id)
|
||||
@@ -58,8 +66,10 @@ class M3Controller extends Controller
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @param int $id
|
||||
*
|
||||
* @return Renderable
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
@@ -69,7 +79,9 @@ class M3Controller extends Controller
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return Renderable
|
||||
*/
|
||||
public function destroy($id)
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use DB;
|
||||
use Config;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Modules\M3\Models\ICM664M;
|
||||
|
||||
|
||||
class M3DeliveryController extends Controller
|
||||
{
|
||||
|
||||
public static function index(Request $request) {
|
||||
$connection = config('m3.connection', 'pgsql');
|
||||
$power_user = (object) ['R428PWRUSR'=>'N','R428US'=>strtoUpper(m3_user()),'R428CO'=>'','R428PL'=>'','R428WH'=>''];
|
||||
if (\Illuminate\Support\Facades\Schema::connection($connection)->hasTable('icm428m')) {
|
||||
$power_user = DB::connection($connection)->table('icm428m')->select('R428PWRUSR','R428US','R428CO','R428PL','R428WH')
|
||||
->where('R428US',strtoUpper(m3_user()))->first() ?? $power_user;
|
||||
}
|
||||
$co=$power_user->R428CO; $plant=$power_user->R428PL; $whs=$power_user->R428WH;
|
||||
$ICM664M = \Illuminate\Support\Facades\Schema::connection($connection)->hasTable('icm664m')
|
||||
? DB::connection($connection)->table('icm664m')->where('AVCO',$co)->where('AVPLANT',$plant)->where('AVWHS',$whs)->get() : collect();
|
||||
$IC670M = \Illuminate\Support\Facades\Schema::connection($connection)->hasTable('ic670m')
|
||||
? DB::connection($connection)->table('ic670m')->where('WDCO',$co)->where('WDPL',$plant)->where('WDWHS',$whs)->get() : collect();
|
||||
$shipvia = \Illuminate\Support\Facades\Schema::connection($connection)->hasTable('icm319m')
|
||||
? DB::connection($connection)->table('icm319m')->select('AXCODE','AXDESC')->orderBy('AXCODE')->get() : collect();
|
||||
return view('m3::liberty-theme.pages.M3Delivery', compact('ICM664M','IC670M','power_user','shipvia'));
|
||||
}
|
||||
|
||||
//
|
||||
// Process data from Add modal
|
||||
//
|
||||
public static function saveM3DeliveryAdd(Request $request) {
|
||||
|
||||
$icm664m=DB::connection(config('m3.connection', 'pgsql'))->select("select count(*) as COUNT1 from ICM664M
|
||||
where AVCO='$request->AVCO' and AVWHS='$request->AVWHS' and AVPLANT='$request->AVPLANT' and AVDELMETH='$request->AVDELMETH'");
|
||||
if($icm664m[0]->COUNT1=="1") {
|
||||
return "exists";
|
||||
} else {
|
||||
|
||||
DB::connection(config('m3.connection', 'pgsql'))->insert("insert into ICM664M
|
||||
(AVCO, AVPLANT, AVWHS, AVDELMETH, AVSHPVIA, AVSHSRT, AVSHORCL)
|
||||
values ('$request->AVCO', '$request->AVPLANT', '$request->AVWHS', '$request->AVDELMETH',
|
||||
'$request->AVSHPVIA', '$request->AVSHSRT', '$request->AVSHORCL')");
|
||||
return "success";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Process data from Edit modal
|
||||
//
|
||||
public static function saveM3DeliveryEdit(Request $request) {
|
||||
#dd($request);
|
||||
// Update record to ICM664M
|
||||
|
||||
DB::connection(config('m3.connection', 'pgsql'))->update("update ICM664M
|
||||
set AVSHPVIA='$request->AVSHPVIA', AVSHSRT='$request->AVSHSRT', AVSHORCL='$request->AVSHORCL'
|
||||
where AVCO='$request->AVCO' and AVPLANT='$request->AVPLANT' and AVWHS='$request->AVWHS' and AVDELMETH='$request->AVDELMETH'");
|
||||
|
||||
return "success";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,348 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use DB;
|
||||
use Config;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Datatables;
|
||||
use Str;
|
||||
use Excel;
|
||||
|
||||
class M3ErrorsDispController extends Controller
|
||||
{
|
||||
|
||||
public static function index(Request $request)
|
||||
{
|
||||
// dump($request->all());
|
||||
$macpkr = isset($request->macpkr) ? trim($request->macpkr) : "";
|
||||
$shsource = isset($request->shsource) ? trim($request->shsource) : "";
|
||||
$showerrors = isset($request->showerrors) ? trim($request->showerrors) : "N";
|
||||
$skipdates = isset($request->skipdates) ? trim($request->skipdates) : "N";
|
||||
|
||||
# Get users from ICM428M
|
||||
$connection = config('m3.connection', 'pgsql');
|
||||
$ICM428M = \Illuminate\Support\Facades\Schema::connection($connection)->hasTable('icm428m')
|
||||
? DB::connection($connection)->table('icm428m')->select('R428US', 'R428FIRST', 'R428FAMILY')->get()
|
||||
: collect();
|
||||
$ICM428MCOL = collect($ICM428M);
|
||||
$ICM428MCOL->filter(function ($value) {
|
||||
return $value->R428US = trim($value->R428US);
|
||||
});
|
||||
$ICM428MCOL->filter(function ($value) {
|
||||
return $value->R428FIRST = trim($value->R428FIRST);
|
||||
});
|
||||
$ICM428MCOL->filter(function ($value) {
|
||||
return $value->R428FAMILY = trim($value->R428FAMILY);
|
||||
});
|
||||
|
||||
return view('m3::liberty-theme.pages.M3ErrorsDisplay', compact('macpkr', 'shsource', 'showerrors', 'skipdates', 'ICM428MCOL'));
|
||||
}
|
||||
|
||||
public function datatables(Request $request)
|
||||
{
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('max_input_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('memory_limit', '1024M');
|
||||
|
||||
// dump($request->all());
|
||||
$SHMACPKR = null != $request->SHMACPKR ? trim($request->SHMACPKR) : '';
|
||||
$SHSOURCE = null != $request->SHSOURCE ? trim($request->SHSOURCE) : '';
|
||||
$STARTDATE = null != $request->STARTDATE ? trim($request->STARTDATE) : today()->subDays(1)->format('Y-m-d');
|
||||
$ENDDATE = null != $request->ENDDATE ? trim($request->ENDDATE) : today()->format('Y-m-d');
|
||||
$SHOWERRORS = null != $request->SHOWERRORS ? trim($request->SHOWERRORS) : 'N';
|
||||
$SHUSER = m3_user() !== '' ? Str::upper(trim(m3_user())) : '';
|
||||
$SKIPDATES = null != $request->SKIPDATES ? trim($request->SKIPDATES) : 'N';
|
||||
|
||||
# Get Logged User CO & WH
|
||||
# Get users from ICM428M
|
||||
$ICM428M = DB::connection(config('m3.connection', 'pgsql'))->table('icm428m')
|
||||
->select('R428US', 'R428CO', 'R428WH')
|
||||
->where('R428US', '=', $SHUSER)
|
||||
->first();
|
||||
|
||||
$R428US = isset($ICM428M->R428US) ? $ICM428M->R428US : '';
|
||||
$USERCO = isset($ICM428M->R428CO) ? $ICM428M->R428CO : '';
|
||||
$USERWH = isset($ICM428M->R428WH) ? $ICM428M->R428WH : '';
|
||||
|
||||
# Merge date and time fields
|
||||
$mergedDateTime = DB::raw(" ICM699M.SHDT || ' ' || ICM699M.SHTIME AS SHDATETIME");
|
||||
|
||||
$ICM699M = DB::connection(config('m3.connection', 'pgsql'))->table('icm699m')
|
||||
->select(
|
||||
'ICM699M.*',
|
||||
'ICM699M.SHACKDATE',
|
||||
'ICM699M.SHACKTIME',
|
||||
'ICM699M.SHACKUSER',
|
||||
$mergedDateTime,
|
||||
'ICM428M.R428FIRST',
|
||||
'ICM428M.R428FAMILY',
|
||||
'ICM688M1.A4ONO',
|
||||
'ICM688M1.A4SHSHNM',
|
||||
'ICM666M.A1ONO',
|
||||
'ICM666M.A1SHSHNM'
|
||||
)
|
||||
->distinct()
|
||||
->leftJoin('ICM428M', 'ICM699M.SHUSER', '=', 'ICM428M.R428US')
|
||||
->leftJoin('ICM688M1', 'ICM699M.SHMACPKR', '=', 'ICM688M1.A4MACPKR')
|
||||
->leftJoin('ICM666M', 'ICM699M.SHMACPKR', '=', 'ICM666M.A1DELNO');
|
||||
|
||||
if ($R428US != '') {
|
||||
$ICM699M->whereIn('SHCO', [$USERCO, '']);
|
||||
$ICM699M->whereIn('SHWHS', [$USERWH, '']);
|
||||
} else {
|
||||
$ICM699M->where('SHCO', null);
|
||||
$ICM699M->where('SHWHS', null);
|
||||
}
|
||||
|
||||
if ($SHMACPKR != '') {
|
||||
$ICM699M->where('SHMACPKR', $SHMACPKR);
|
||||
}
|
||||
|
||||
if ($SHSOURCE != '') {
|
||||
$ICM699M->where('SHSOURCE', $SHSOURCE);
|
||||
}
|
||||
# Disable PDFStorage Search
|
||||
$ICM699M->where('SHSOURCE', '!=', 'PdfStorageAPI');
|
||||
|
||||
if ($SHMACPKR == '' && $SKIPDATES == 'N') {
|
||||
$ICM699M->whereBetween('SHDT', [$STARTDATE, $ENDDATE]);
|
||||
}
|
||||
|
||||
if ($SHOWERRORS == 'Y') {
|
||||
$ICM699M->where('SHERROR', 'X');
|
||||
}
|
||||
|
||||
# Get only M3 Logs
|
||||
$ICM699M->where('SHTYPE', 'like', '%M3%');
|
||||
|
||||
return Datatables::of($ICM699M)->addIndexColumn()->make(true);
|
||||
}
|
||||
|
||||
public static function update699M(Request $request)
|
||||
{
|
||||
// dump($request->all());
|
||||
$SHMACPKR = null != $request->SHMACPKR ? trim($request->SHMACPKR) : '';
|
||||
$SHSOURCE = null != $request->SHSOURCE ? trim($request->SHSOURCE) : '';
|
||||
$SHCO = null != $request->SHCO ? trim($request->SHCO) : '';
|
||||
$SHWHS = null != $request->SHWHS ? trim($request->SHWHS) : '';
|
||||
$SHDT = null != $request->SHDT ? trim($request->SHDT) : '';
|
||||
$SHTIME = null != $request->SHTIME ? trim($request->SHTIME) : '';
|
||||
$SHTYPE = null != $request->SHTYPE ? trim($request->SHTYPE) : '';
|
||||
$SHACKNOTE = null != $request->SHACKNOTE ? trim(substr($request->SHACKNOTE, 0, 99)) : '';
|
||||
$SHUSER = m3_user() !== '' ? Str::upper(m3_user()) : '';
|
||||
$CLOSESIM = null != $request->CLOSESIM ? trim($request->CLOSESIM) : 'N';
|
||||
|
||||
if ($CLOSESIM == 'N') {
|
||||
$ICM699MU = DB::connection(config('m3.connection', 'pgsql'))->table('icm699m')
|
||||
->where('SHMACPKR', $SHMACPKR)
|
||||
->where('SHDT', $SHDT)
|
||||
->where('SHTIME', $SHTIME)
|
||||
->where('SHCO', $SHCO)
|
||||
->where('SHWHS', $SHWHS)
|
||||
->where('SHSOURCE', $SHSOURCE)
|
||||
->where('SHERROR', 'X')
|
||||
->where('SHTYPE', $SHTYPE)
|
||||
->update(["SHERROR" => "Z", "SHACKUSER" => $SHUSER, "SHACKDATE" => date('Y-m-d'), "SHACKTIME" => date('H:i:s'), "SHACKNOTE" => $SHACKNOTE]);
|
||||
|
||||
} else {
|
||||
$ICM699MU = DB::connection(config('m3.connection', 'pgsql'))->table('icm699m')
|
||||
->where('SHCO', $SHCO)
|
||||
->where('SHWHS', $SHWHS)
|
||||
->where('SHSOURCE', $SHSOURCE)
|
||||
->where('SHERROR', 'X')
|
||||
->where('SHTYPE', $SHTYPE)
|
||||
->update(["SHERROR" => "Z", "SHACKUSER" => $SHUSER, "SHACKDATE" => date('Y-m-d'), "SHACKTIME" => date('H:i:s'), "SHACKNOTE" => $SHACKNOTE]);
|
||||
}
|
||||
|
||||
|
||||
if ($SHSOURCE == "CloseShipmentCoChargeAPI") {
|
||||
# Update ICM688M1 : Change A4PICKSTS
|
||||
DB::connection(config('m3.connection', 'pgsql'))->table('icm688m1')
|
||||
->where('A4MACPKR', $SHMACPKR)
|
||||
->where('A4CO', $SHCO)
|
||||
->where('A4WHS', $SHWHS)
|
||||
->update(['A4PICKSTS' => 'a']);
|
||||
}
|
||||
|
||||
return response()->json(['success' => true]);
|
||||
}
|
||||
|
||||
# Export To Excel
|
||||
public static function exporttoExcel(Request $request)
|
||||
{
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('max_input_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('memory_limit', '1024M');
|
||||
|
||||
try {
|
||||
// dd($request->all());
|
||||
$SHMACPKR = null != $request->SHMACPKR ? trim($request->SHMACPKR) : '';
|
||||
$SHSOURCE = null != $request->SHSOURCE ? trim($request->SHSOURCE) : '';
|
||||
$STARTDATE = null != $request->STARTDATE ? trim($request->STARTDATE) : today()->subDays(1)->format('Y-m-d');
|
||||
$ENDDATE = null != $request->ENDDATE ? trim($request->ENDDATE) : today()->format('Y-m-d');
|
||||
$SHOWERRORS = null != $request->SHOWERRORS ? trim($request->SHOWERRORS) : 'N';
|
||||
$SHUSER = m3_user() !== '' ? Str::upper(trim(m3_user())) : '';
|
||||
$SKIPDATES = null != $request->SKIPDATES ? trim($request->SKIPDATES) : 'N';
|
||||
# Get Logged User CO & WH
|
||||
# Get users from ICM428M
|
||||
$ICM428M = DB::connection(config('m3.connection', 'pgsql'))->table('icm428m')
|
||||
->select('R428US', 'R428CO', 'R428WH')
|
||||
->where('R428US', '=', $SHUSER)
|
||||
->first();
|
||||
|
||||
$R428US = isset($ICM428M->R428US) ? $ICM428M->R428US : '';
|
||||
$USERCO = isset($ICM428M->R428CO) ? $ICM428M->R428CO : '';
|
||||
$USERWH = isset($ICM428M->R428WH) ? $ICM428M->R428WH : '';
|
||||
|
||||
# Get users from ICM428M
|
||||
$ICM428MAll = DB::connection(config('m3.connection', 'pgsql'))->table('icm428m')
|
||||
->select('R428US', 'R428FIRST', 'R428FAMILY')
|
||||
->get();
|
||||
$ICM428MCOL = collect($ICM428MAll);
|
||||
$ICM428MCOL->filter(function ($value) {
|
||||
return $value->R428US = trim($value->R428US);
|
||||
});
|
||||
$ICM428MCOL->filter(function ($value) {
|
||||
return $value->R428FIRST = trim($value->R428FIRST);
|
||||
});
|
||||
$ICM428MCOL->filter(function ($value) {
|
||||
return $value->R428FAMILY = trim($value->R428FAMILY);
|
||||
});
|
||||
|
||||
# Merge date and time fields
|
||||
$mergedDateTime = DB::raw(" ICM699M.SHDT || ' ' || ICM699M.SHTIME AS SHDATETIME");
|
||||
|
||||
$ICM699M = DB::connection(config('m3.connection', 'pgsql'))->table('icm699m')
|
||||
->select(
|
||||
DB::raw('COALESCE(ICM688M1.A4ONO, ICM666M.A1ONO) AS DELIVERY_NUM '),
|
||||
'ICM699M.SHMACPKR',
|
||||
DB::raw('COALESCE(ICM688M1.A4SHSHNM, ICM666M.A1SHSHNM) AS CUSTOMER '),
|
||||
$mergedDateTime,
|
||||
DB::raw("CASE WHEN ICM699M.SHERROR !='Z' THEN TRIM(ICM699M.SHERROR) ELSE 'Closed' END AS ERROR"),
|
||||
'ICM699M.SHTYPE',
|
||||
'ICM699M.SHSOURCE',
|
||||
DB::raw("CASE WHEN ICM428M.R428FIRST IS NOT NULL THEN TRIM(ICM428M.R428FIRST) ||' '|| TRIM(ICM428M.R428FAMILY) ELSE TRIM(ICM699M.SHUSER) END AS USER"),
|
||||
'ICM699M.SHCODE',
|
||||
'ICM699M.SHCO',
|
||||
'ICM699M.SHWHS',
|
||||
DB::raw(" ICM699M.SHACKDATE ||' '||ICM699M.SHACKTIME AS ACKDATE"),
|
||||
'ICM699M.SHACKUSER',
|
||||
'ICM699M.SHINTBOX',
|
||||
'ICM699M.SHACKNOTE',
|
||||
DB::raw('SUBSTR(ICM699M.SHDATA, 1, 200)')
|
||||
)
|
||||
->distinct()
|
||||
->leftJoin('ICM428M', 'ICM699M.SHUSER', '=', 'ICM428M.R428US')
|
||||
->leftJoin('ICM688M1', 'ICM699M.SHMACPKR', '=', 'ICM688M1.A4MACPKR')
|
||||
->leftJoin('ICM666M', 'ICM699M.SHMACPKR', '=', 'ICM666M.A1DELNO');
|
||||
|
||||
# Get Records Count only
|
||||
$ICM699MC = DB::connection(config('m3.connection', 'pgsql'))->table('icm699m');
|
||||
|
||||
if ($R428US != '') {
|
||||
$ICM699M->whereIn('SHCO', [$USERCO, '']);
|
||||
$ICM699M->whereIn('SHWHS', [$USERWH, '']);
|
||||
|
||||
$ICM699MC->whereIn('SHCO', [$USERCO, '']);
|
||||
$ICM699MC->whereIn('SHWHS', [$USERWH, '']);
|
||||
} else {
|
||||
$ICM699M->where('SHCO', null);
|
||||
$ICM699M->where('SHWHS', null);
|
||||
|
||||
$ICM699MC->where('SHCO', null);
|
||||
$ICM699MC->where('SHWHS', null);
|
||||
}
|
||||
|
||||
if ($SHMACPKR != '') {
|
||||
$ICM699M->where('SHMACPKR', $SHMACPKR);
|
||||
|
||||
$ICM699MC->where('SHMACPKR', $SHMACPKR);
|
||||
}
|
||||
|
||||
if ($SHSOURCE != '') {
|
||||
$ICM699M->where('SHSOURCE', $SHSOURCE);
|
||||
|
||||
$ICM699MC->where('SHSOURCE', $SHSOURCE);
|
||||
}
|
||||
# Disable PDFStorage Search
|
||||
$ICM699M->where('SHSOURCE', '!=', 'PdfStorageAPI');
|
||||
|
||||
$ICM699MC->where('SHSOURCE', '!=', 'PdfStorageAPI');
|
||||
|
||||
if ($SHMACPKR == '' && $SKIPDATES == 'N') {
|
||||
$ICM699M->whereBetween('SHDT', [$STARTDATE, $ENDDATE]);
|
||||
|
||||
$ICM699MC->whereBetween('SHDT', [$STARTDATE, $ENDDATE]);
|
||||
}
|
||||
|
||||
if ($SHOWERRORS == 'Y') {
|
||||
$ICM699M->where('SHERROR', 'X');
|
||||
|
||||
$ICM699MC->where('SHERROR', 'X');
|
||||
}
|
||||
|
||||
# Get only M3 Logs
|
||||
$ICM699M->where('SHTYPE', 'like', '%M3%');
|
||||
|
||||
$ICM699MC->where('SHTYPE', 'like', '%M3%');
|
||||
|
||||
# Count records before exporting to excel : Max 20K records are allowed
|
||||
$ICM699MCount = $ICM699MC->count();
|
||||
// dd($ICM699MCount);
|
||||
# Set Max allowed records
|
||||
$maxRecords = Config::get('arrays.maxRecDL');
|
||||
if ($ICM699MCount > $maxRecords) {
|
||||
return redirect()->back()->withInput()->with('message', 'Maximum allowed records for Excel Download is: ' . number_format($maxRecords) .
|
||||
' current records: ' . number_format($ICM699MCount) . ' , change your search criteria.');
|
||||
}
|
||||
|
||||
# Select Records and export them to Excel
|
||||
$ICM699MSel = $ICM699M->get();
|
||||
$ICM699MCol = collect($ICM699MSel);
|
||||
|
||||
# Get Transaction Types
|
||||
$transxTypes = Config::get('arrays.transxTypes');
|
||||
$ICM699MCol->filter(function ($value) use ($transxTypes) {
|
||||
return $value->SHSOURCE = isset($transxTypes[trim($value->SHSOURCE)]) ? $transxTypes[trim($value->SHSOURCE)] : $value->SHSOURCE;
|
||||
});
|
||||
|
||||
# Get User Names
|
||||
$ICM699MCol->filter(function ($value) use ($ICM428MCOL) {
|
||||
$UserTemp = $ICM428MCOL->firstWhere('R428US', trim($value->SHACKUSER));
|
||||
$SHACKUSER = isset($UserTemp->R428FIRST) ? $UserTemp->R428FIRST . ' ' . $UserTemp->R428FAMILY : trim($value->SHACKUSER);
|
||||
return $value->SHACKUSER = $SHACKUSER;
|
||||
});
|
||||
|
||||
# Prepend Header To Excel
|
||||
$newItem = ["SHMACPKR" => 'Delivery Note',
|
||||
"DELIVERY_NUM" => 'Order #',
|
||||
"CUSTOMER" => 'Customer',
|
||||
"SHDATETIME" => 'Date',
|
||||
"ERROR" => 'Error',
|
||||
"SHTYPE" => 'Request Type',
|
||||
"SHSOURCE" => 'Source of transaction',
|
||||
"USER" => 'User',
|
||||
"SHCODE" => 'Request or Response Data',
|
||||
"SHCO" => 'Division',
|
||||
"SHWHS" => 'Warehouse',
|
||||
"ACKDATE" => 'Acknowledge/Retry Date',
|
||||
"SHACKUSER" => 'Acknowledged/Retried by User',
|
||||
"SHINTBOX" => 'Internal Box Number',
|
||||
"SHACKNOTE" => 'Note',
|
||||
"SHDATA" => 'Error description'
|
||||
];
|
||||
$ICM699MCol->prepend($newItem);
|
||||
// dd($ICM699MCol);
|
||||
|
||||
# Download Excel File
|
||||
return app(\Modules\M3\Services\SpreadsheetExport::class)->download($ICM699MCol, 'transactionLog_' . $STARTDATE . '-' . $ENDDATE . '.xlsx');
|
||||
} catch (\Throwable $th) {
|
||||
Log::error($th);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use DB;
|
||||
use Config;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
// use Datatables;
|
||||
use Smalot\PdfParser\Parser;
|
||||
use File;
|
||||
use Cache;
|
||||
use Str;
|
||||
|
||||
class M3GetPDFFromCacheController extends Controller
|
||||
{
|
||||
public static function index(Request $request){
|
||||
// Parse PDF file and build necessary objects.
|
||||
$parser = new \Smalot\PdfParser\Parser();
|
||||
|
||||
$aggno = $aggmsg = "";
|
||||
$IC670M = $PDFArray = $carrier = $trackingno = $ICM688M1 = [];
|
||||
$AYMACPKR = $WHDDA = $COMPANY = $PLANT = $WHS = '';
|
||||
#$carrier = $trackingno = "";
|
||||
|
||||
# PDF File PATH
|
||||
$pdfFilePath = Config::get('arrays.PdfPath');
|
||||
try {
|
||||
# Initialise Vars
|
||||
$PDFArray = $trackingno = $carrier = $ICM688M1 = [];
|
||||
|
||||
$SHUSER = m3_user() !== '' ? Str::upper(trim(m3_user())) : '';
|
||||
// dd($SHUSER);
|
||||
|
||||
if ($SHUSER!='') {
|
||||
# Get User CO & WH
|
||||
# Get user from ICM428M
|
||||
$ICM428M = DB::connection(config('m3.connection', 'pgsql'))->table('icm428m')
|
||||
->select('R428US','R428CO', 'R428WH','R428PL')
|
||||
->where('R428US','=',$SHUSER)
|
||||
->first();
|
||||
|
||||
$R428US = isset($ICM428M->R428US) ? $ICM428M->R428US : '';
|
||||
$COMPANY = isset($ICM428M->R428CO) ? $ICM428M->R428CO : ''; # Company
|
||||
$PLANT = isset($ICM428M->R428PL) ? $ICM428M->R428PL : ''; # Plant
|
||||
$WHS = isset($ICM428M->R428WH) ? $ICM428M->R428WH : ''; # WareHouse
|
||||
}
|
||||
|
||||
# Warehouse Table
|
||||
$IC670M = DB::connection(config('m3.connection', 'pgsql'))->table('ic670m')->get();
|
||||
// ->where('WDCO',$userCO)->where('WDPL',$userPL)->where('WDWHS',$userWH)
|
||||
|
||||
# Get URL PARAMS
|
||||
$urlParams = count($request->all())>0 ? $request->all() : '';
|
||||
// dump($urlParams);
|
||||
$AYMACPKR = isset($urlParams["MACPKR"]) ? trim($urlParams["MACPKR"]) : ''; # Delivery note number
|
||||
$DOCTYPE = isset($urlParams["DOCTYPE"]) ? trim($urlParams["DOCTYPE"]) : ''; # Document type (PackingList, CarrierLabel, ContentLabel)
|
||||
$WHDDA = $COMPANY.$PLANT.$WHS;
|
||||
// dump($WHDDA);
|
||||
|
||||
# Check Doctype fisrt
|
||||
$docTypes = $DOCTYPE!='' ? [$DOCTYPE] : ['PackingList','ContentLabel', 'CarrierLabel', 'GSLabel']; # document type (PackingList, CarrierLabel, ContentLabel)
|
||||
|
||||
if($urlParams!=''){
|
||||
// dump($urlParams);
|
||||
# document number (ie the internal box number, the pick list number)
|
||||
# Key Combination : COMPANY WHS A4MACPKR DOCTYPE DOCNUM
|
||||
# Document type (PackingList, CarrierLabel, ContentLabel)
|
||||
|
||||
# Get Aggregation Number if it exists
|
||||
$ICM695M1Agg = DB::connection(config('m3.connection', 'pgsql'))->table('icm695m1')
|
||||
->select('AYTRUCK')
|
||||
->where('AYCO',$COMPANY)
|
||||
->where('AYWHS',$WHS)
|
||||
->where('AYMACPKR',$AYMACPKR)
|
||||
->first();
|
||||
// dump($ICM695M1Agg);
|
||||
$aggno = isset($ICM695M1Agg->AYTRUCK) ? trim($ICM695M1Agg->AYTRUCK) : '';
|
||||
|
||||
if($aggno!="" && $aggno!="0") {
|
||||
// dump($aggno);
|
||||
|
||||
$aggmsg="This delivery note is part of aggregation $aggno ";
|
||||
$ICM688M1 = DB::connection(config('m3.connection', 'pgsql'))->select("select A4MACPKR from ICM688M1 where A4SHPAGGCD='$aggno'");
|
||||
#dump($ICM688M1);
|
||||
// foreach($ICM688M1 as $key => $ICM688M1R) {
|
||||
// $aggmsg.=' <a href="M3GetPDFFromCache?MACPKR='.$ICM688M1R->A4MACPKR.'&COMPANY='.$COMPANY.'&PLANT='.$PLANT.'&WHS='.$WHS.'">'.$ICM688M1R->A4MACPKR.'</a>';
|
||||
// }
|
||||
// $aggmsg.=" )";
|
||||
|
||||
#654 add 'AYSPR15A01', 'AYSPR30A01', 'AYTRUCK' carrier and tracking# and agg#
|
||||
$ICM695M1 = DB::connection(config('m3.connection', 'pgsql'))->table('icm695m1')
|
||||
->select('AYCO','AYWHS','AYMACPKR','AYINTBOX', 'AYSPR15A01', 'AYSPR30A01', 'AYTRUCK')
|
||||
->distinct()
|
||||
->where('AYCO',$COMPANY)
|
||||
->where('AYWHS',$WHS)
|
||||
// ->where('AYMACPKR',$AYMACPKR)
|
||||
->where('AYTRUCK',$aggno)
|
||||
->orderBy('AYMACPKR')
|
||||
->get();
|
||||
}
|
||||
else{
|
||||
#654 add 'AYSPR15A01', 'AYSPR30A01', 'AYTRUCK' carrier and tracking# and agg#
|
||||
$ICM695M1 = DB::connection(config('m3.connection', 'pgsql'))->table('icm695m1')
|
||||
->select('AYCO','AYWHS','AYMACPKR','AYINTBOX', 'AYSPR15A01', 'AYSPR30A01', 'AYTRUCK')
|
||||
->distinct()
|
||||
->where('AYCO',$COMPANY)
|
||||
->where('AYWHS',$WHS)
|
||||
->where('AYMACPKR',$AYMACPKR)
|
||||
->orderBy('AYMACPKR')
|
||||
->get();
|
||||
}
|
||||
#dump($ICM695M1);
|
||||
|
||||
$allLabels = [];
|
||||
|
||||
if (count($ICM695M1)>0) {
|
||||
$tmpCacheArr = $carrier = $trackingno = [];
|
||||
# Loop the Results from $ICM595M1TMP
|
||||
foreach ($ICM695M1 as $key => $ICM695M1R) {
|
||||
$WHS = trim($ICM695M1R->AYWHS);
|
||||
$COMPANY = trim($ICM695M1R->AYCO);
|
||||
$AYMACPKR = trim($ICM695M1R->AYMACPKR);
|
||||
$DOCNUM = trim($ICM695M1R->AYINTBOX);
|
||||
#654
|
||||
$carrier[] = trim($ICM695M1R->AYSPR15A01);
|
||||
$trackingno[] = trim($ICM695M1R->AYSPR30A01);
|
||||
$aggno = trim($ICM695M1R->AYTRUCK);
|
||||
|
||||
# Make Key and Test Validity
|
||||
if ($AYMACPKR!='' && $COMPANY!='' && $WHS!=''){
|
||||
//echo "<script>alert('2');</script>";
|
||||
$CarrierLabel = '';
|
||||
$ContentLabel = '';
|
||||
$PackingList = '';
|
||||
$cacheKeyPackingList = $cacheKeyCarrierLabel = $cacheKeyContentLabel = '';
|
||||
|
||||
# Get Unique Keys
|
||||
foreach ($docTypes as $key => $value) {
|
||||
# Check Parcel vs LTL
|
||||
if( $value == 'ContentLabel' ){
|
||||
$DOCNUMT = $DOCNUM;
|
||||
$ContentLabel = !is_numeric($DOCNUM) ? 'LTL' : '';
|
||||
}
|
||||
|
||||
if( $value == 'CarrierLabel' ){
|
||||
$DOCNUMT = $DOCNUM;
|
||||
|
||||
# Keep Solon Logic to read LTL
|
||||
$DOCNUMT2 = $ContentLabel=='LTL' ? $AYMACPKR : $DOCNUM;
|
||||
if ($DOCNUMT2!=$DOCNUMT) {
|
||||
$PDFKey2 = $value.'/'.$value.'_'.$AYMACPKR.'_'.$DOCNUMT2.'_'.$COMPANY.'_'.$WHS;
|
||||
$tmpCacheArr[] = $PDFKey2;
|
||||
}
|
||||
}
|
||||
|
||||
if( $value == 'PackingList' ){
|
||||
$DOCNUMT = $AYMACPKR;
|
||||
}
|
||||
|
||||
# Get GS1 Labels
|
||||
if($value=='GSLabel' ){
|
||||
$PDFKey = $value.'/'.$value.'_'.$AYMACPKR.'_'.$COMPANY.'_'.$WHS.'_'.$DOCNUM;
|
||||
|
||||
// if ($ContentLabel=='LTL' ) {
|
||||
// $PDFKey = $value.'/'.$value.'_'.$AYMACPKR.'_'.$COMPANY.'_'.$WHS;
|
||||
// }
|
||||
// else{
|
||||
// $PDFKey = $value.'/'.$value.'_'.$AYMACPKR.'_'.$COMPANY.'_'.$WHS.'_'.$DOCNUM;
|
||||
// }
|
||||
}
|
||||
else{
|
||||
$PDFKey = $value.'/'.$value.'_'.$AYMACPKR.'_'.$DOCNUMT.'_'.$COMPANY.'_'.$WHS;
|
||||
}
|
||||
$tmpCacheArr[] = $PDFKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
// dump($tmpCacheArr);
|
||||
|
||||
# Get unique values from array $PDFArray
|
||||
$tmpCacheArr = collect($tmpCacheArr)->unique();
|
||||
// dump($tmpCacheArr);
|
||||
foreach($tmpCacheArr as $key => $value){
|
||||
// $isCarrierLabel = Str::contains($value, 'CarrierLabel');
|
||||
|
||||
$pdfFileName = $pdfFilePath.$value.'.pdf';
|
||||
if(File::exists($pdfFileName)){
|
||||
// dump($pdfFileName);
|
||||
|
||||
$pdfFile = File::get($pdfFileName);
|
||||
# Transform content to base64
|
||||
// $base64PDF = $pdfFile;
|
||||
$base64PDF = base64_encode($pdfFile);
|
||||
// dd($base64PDF);
|
||||
$PDFArray[] = $base64PDF;
|
||||
}
|
||||
}
|
||||
// dump($PDFArray);
|
||||
}
|
||||
else {
|
||||
# Nothing Found
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (\Throwable $th) {
|
||||
// Log::error($th);
|
||||
}
|
||||
# dump($PDFArray);
|
||||
# dump($AYMACPKR);
|
||||
# dump($IC670M);
|
||||
# dump($ICM695M1);
|
||||
|
||||
return view('m3::liberty-theme.pages.M3GetPDF',compact('IC670M','PDFArray','AYMACPKR','WHDDA','aggmsg','carrier','trackingno','ICM688M1','COMPANY','PLANT','WHS'));
|
||||
// compact('IC670M','ViewTitle')
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
namespace Modules\M3\Http\Controllers;
|
||||
|
||||
use DB;
|
||||
use Config;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class MFOrdersController extends Controller
|
||||
{
|
||||
|
||||
public static function index(Request $request)
|
||||
{
|
||||
$MF = isset($request->id) ? trim($request->id) : "";
|
||||
|
||||
// dd("MFOrders ".$MF);
|
||||
# Get Users from ICM428M
|
||||
$ICM428M = DB::connection(config('m3.connection', 'pgsql'))->table('icm428m')
|
||||
->select('R428US','R428CO', 'R428WH', 'R428PL')
|
||||
->where('R428US','=',strtoUpper(m3_user()))
|
||||
->first();
|
||||
$user = $ICM428M->R428US;
|
||||
$co = $ICM428M->R428CO;
|
||||
$whs = $ICM428M->R428WH;
|
||||
$plant = $ICM428M->R428PL;
|
||||
|
||||
# ICM705M1 Statement
|
||||
$sqlstmt = "select APMANIFEST,APDOCKDOOR,APCARRIER,APTRUCKIDT,APSPARE1,APLDSTRU,APLDSTRD,APLDSTRT,
|
||||
APLDCLOU,APLDCLOD,APLDCLOT,APCO,APWHS,APPLT,APSPARE2,APLDCLOZ
|
||||
from ICM705M1
|
||||
where APMANIFEST = $MF and APCO='$co' and APWHS='$whs' and APPLT='$plant' limit 1";
|
||||
|
||||
$ICM705M1 = DB::connection(config('m3.connection', 'pgsql'))->select($sqlstmt);
|
||||
// dump($ICM705M1);
|
||||
$carrier = isset($ICM705M1[0]->APCARRIER) ? trim($ICM705M1[0]->APCARRIER) : "";
|
||||
|
||||
if ($MF!='') {
|
||||
$status_ICM688M1_array = Config::get('arrays.status_ICM688M1_array');
|
||||
|
||||
$sqlstmt = "SELECT AYCO,AYPLANT,AYMACPKR,AYONO,A4SHSHNM,A4PICKSTS,AYSPR15A01,SUM(AYLNWGHT) AS TOTWEIGHT,COUNT(*) AS BOXPAL FROM ICM695M1
|
||||
LEFT JOIN ICM688M1 ON AYCO=A4CO AND AYPLANT=A4PLANT AND AYMACPKR=A4MACPKR
|
||||
WHERE AYAPRF1551= $MF and AYCO='$co' and AYWHS='$whs' and AYPLANT='$plant'
|
||||
GROUP BY AYCO,AYPLANT,AYMACPKR,AYONO,A4SHSHNM,A4PICKSTS,AYSPR15A01";
|
||||
|
||||
$ICM695M1 = DB::connection(config('m3.connection', 'pgsql'))->select($sqlstmt);
|
||||
// dump($ICM695M1);
|
||||
|
||||
return view('m3::liberty-theme.pages.MFOrders', compact( 'ICM695M1', 'status_ICM688M1_array', 'MF', 'carrier')
|
||||
);
|
||||
}
|
||||
else{
|
||||
abort(404, 'Manifest Not Found');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use DB;
|
||||
use Config;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Str;
|
||||
use Log;
|
||||
use Excel;
|
||||
use Storage;
|
||||
|
||||
class OrderLinesOfClosedOrder extends Controller
|
||||
{
|
||||
public static function index(Request $request){
|
||||
$IC670M = $ICM688M2 = [];
|
||||
$WHDDA = $COMPANY = $PLANT = $WHS = '';
|
||||
$REPORTDATEDisp = today()->format('Ymd');
|
||||
$allReportsUrls = [];
|
||||
try {
|
||||
$SHUSER = m3_user() !== '' ? Str::upper(trim(m3_user())) : '';
|
||||
// dd($SHUSER);
|
||||
|
||||
if ($SHUSER!='') {
|
||||
# Get User CO & WH from Table ICM428M
|
||||
$ICM428M = DB::connection(config('m3.connection', 'pgsql'))->table('icm428m')
|
||||
->select('R428US','R428CO', 'R428WH','R428PL')
|
||||
->where('R428US','=',$SHUSER)
|
||||
->first();
|
||||
|
||||
$R428US = isset($ICM428M->R428US) ? $ICM428M->R428US : ''; # User
|
||||
$COMPANY = isset($ICM428M->R428CO) ? $ICM428M->R428CO : '110'; # Company
|
||||
$PLANT = isset($ICM428M->R428PL) ? $ICM428M->R428PL : '144'; # Plant
|
||||
$WHS = isset($ICM428M->R428WH) ? $ICM428M->R428WH : '322'; # WareHouse
|
||||
}
|
||||
|
||||
# Warehouse Table
|
||||
$IC670M = DB::connection(config('m3.connection', 'pgsql'))->table('ic670m')->get();
|
||||
|
||||
# Get URL PARAMS
|
||||
$urlParams = count($request->all())>0 ? $request->all() : '';
|
||||
// dump($urlParams);
|
||||
$REPORTDATEDisp = isset($urlParams["REPORTDATEDisp"]) ? \DateTime::createFromFormat('Y-m-d', trim($urlParams["REPORTDATEDisp"]))->format('Ymd') : today()->format('Ymd');
|
||||
|
||||
$WHDDA = $COMPANY.$PLANT.$WHS;
|
||||
// dump($WHDDA);
|
||||
if($REPORTDATEDisp!='' && $COMPANY!='' && $WHS!='' && $PLANT!=''){
|
||||
# Case 729: Add Currency code A1SHCURR FROM ICM666M
|
||||
$selectContent = "
|
||||
SELECT A5MACPKR, A5ONO,
|
||||
(SELECT A4REFORD FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) AS A4REFORD,
|
||||
A5PART, A5RSVQTY, A5PACKED, A5RSVQTY - A5PACKED AS CALCULATED_COLUMN,
|
||||
A5SLUNPR * A5PACKED AS ANOTHER_CALCULATED_COLUMN,
|
||||
A5PMPWHT*A5PACKED AS WEIGHT,
|
||||
(SELECT A4SHSHNM FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) AS A4SHSHNM ,
|
||||
SHDT, SHTIME,
|
||||
CASE WHEN SHDT IS NULL THEN (SELECT SHDATA FROM ICM699M WHERE SHMACPKR=A5MACPKR AND SHTYPE='M3-Res-out' AND SHSOURCE='CloseShipmentCoChargeAPI' ORDER BY SHDT DESC, SHTIME DESC FETCH FIRST 1 ROWS ONLY) ELSE '' END AS REASON,
|
||||
A1SHCURR,
|
||||
CASE
|
||||
WHEN (SELECT A4SHIPTYPE FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) = 'LTL'
|
||||
THEN (SELECT A4RATETCP FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) * ".(100.00 - Config::get('arrays.misc.discountCarrierRateForCustomerPriceLTL'))/100 ."
|
||||
ELSE (SELECT A4RATETCP FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) * ".(100.00 - Config::get('arrays.misc.discountCarrierRateForCustomerPriceParcel') )/100 ."
|
||||
END AS FREIGHT,
|
||||
A4SHIPTYPE,
|
||||
A4SHIPVIA1,
|
||||
A4SCAC,
|
||||
A4OFSTRM
|
||||
FROM ICM688M2
|
||||
LEFT JOIN ICM699M ON SHMACPKR=A5MACPKR AND SHTYPE='M3-Res-out' AND SHDATA LIKE 'Success%' AND SHSOURCE='CloseShipmentCoChargeAPI'
|
||||
LEFT JOIN ICM666M ON A1DELNO=A5MACPKR AND A1ONO=A5ONO AND A1PKLN=A5BRADLN
|
||||
LEFT JOIN ICM688M1 ON A4MACPKR=A5MACPKR
|
||||
WHERE A5MACPKR IN (
|
||||
SELECT DISTINCT AYMACPKR
|
||||
FROM ICM695M1
|
||||
WHERE AYSTATUS IN ('Z','z') AND AYAPR8N002 = $REPORTDATEDisp
|
||||
)
|
||||
AND A5CO=$COMPANY AND A5WHS=$WHS AND A5PLANT=$PLANT";
|
||||
// dump($selectContent);
|
||||
|
||||
$ICM688M2 = DB::connection(config('m3.connection', 'pgsql'))
|
||||
->select($selectContent);
|
||||
// dd($ICM688M2);
|
||||
}
|
||||
else{
|
||||
$ICM688M2 = collect();
|
||||
}
|
||||
|
||||
# Get List of Files
|
||||
$allReportsUrls = [];
|
||||
if ($WHS == '321') {
|
||||
$files = Storage::disk('publicCL')->files();
|
||||
}
|
||||
else{
|
||||
$files = Storage::disk('publicCL')->allFiles($WHS);
|
||||
}
|
||||
|
||||
foreach ($files as $file) {
|
||||
# Get the file URL (if URL is configured in filesystems.php)
|
||||
$url = Storage::disk('publicCL')->url($file);
|
||||
$allReportsUrls[$file] = $url;
|
||||
}
|
||||
|
||||
}
|
||||
catch (\Throwable $th) {
|
||||
Log::error($th);
|
||||
}
|
||||
|
||||
return view('m3::liberty-theme.pages.OrderLinesOfClosed',compact('IC670M','ICM688M2','WHDDA','COMPANY','PLANT','WHS','REPORTDATEDisp','allReportsUrls'));
|
||||
}
|
||||
|
||||
public static function exporttoExcel(Request $request){
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('max_input_time', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOut'));
|
||||
ini_set('memory_limit', '1024M');
|
||||
|
||||
try {
|
||||
$SHUSER = m3_user() !== '' ? Str::upper(trim(m3_user())) : '';
|
||||
// dd($SHUSER);
|
||||
|
||||
if ($SHUSER!='') {
|
||||
# Get User CO & WH from Table ICM428M
|
||||
$ICM428M = DB::connection(config('m3.connection', 'pgsql'))->table('icm428m')
|
||||
->select('R428US','R428CO', 'R428WH','R428PL')
|
||||
->where('R428US','=',$SHUSER)
|
||||
->first();
|
||||
|
||||
$R428US = isset($ICM428M->R428US) ? $ICM428M->R428US : ''; # User
|
||||
$COMPANY = isset($ICM428M->R428CO) ? $ICM428M->R428CO : ''; # Company
|
||||
$PLANT = isset($ICM428M->R428PL) ? $ICM428M->R428PL : ''; # Plant
|
||||
$WHS = isset($ICM428M->R428WH) ? $ICM428M->R428WH : ''; # WareHouse
|
||||
}
|
||||
|
||||
# Warehouse Table
|
||||
$IC670M = DB::connection(config('m3.connection', 'pgsql'))->table('ic670m')->get();
|
||||
|
||||
# Get URL PARAMS
|
||||
$urlParams = count($request->all())>0 ? $request->all() : '';
|
||||
// dd($urlParams);
|
||||
$reportDate = isset($urlParams["REPORTDATE"]) ? \DateTime::createFromFormat('Y-m-d', trim($urlParams["REPORTDATE"]))->format('Ymd') : today()->format('Ymd');
|
||||
$toreportDate = isset($urlParams["TOREPORTDATE"]) ? \DateTime::createFromFormat('Y-m-d', trim($urlParams["TOREPORTDATE"]))->format('Ymd') : today()->format('Ymd');
|
||||
|
||||
$reportDateWD = isset($urlParams["REPORTDATE"]) ? trim($urlParams["REPORTDATE"]) : today()->format('Y-m-d');
|
||||
$toreportDateWD = isset($urlParams["TOREPORTDATE"]) ? trim($urlParams["TOREPORTDATE"]) : today()->format('Y-m-d');
|
||||
|
||||
$WHDDA = $COMPANY.$PLANT.$WHS;
|
||||
// dump($WHDDA);
|
||||
if($reportDate!='' && $COMPANY!='' && $WHS!='' && $PLANT!=''){
|
||||
# Case 729: Add Currency code A1SHCURR FROM ICM666M
|
||||
$selectContent = "
|
||||
SELECT (SHDT || ' ' || SHTIME) AS DATECLOSED, A5MACPKR, A5ONO,
|
||||
A4OFSTRM,
|
||||
A5PMPWHT*A5PACKED AS WEIGHT,
|
||||
A4SCAC,
|
||||
A4SHIPTYPE,
|
||||
(SELECT A4REFORD FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) AS A4REFORD,
|
||||
A5PART, A5RSVQTY, A5PACKED, A5RSVQTY - A5PACKED AS CALCULATED_COLUMN,
|
||||
A5SLUNPR * A5PACKED AS ANOTHER_CALCULATED_COLUMN,
|
||||
(SELECT A4SHSHNM FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) AS A4SHSHNM ,
|
||||
CASE WHEN SHDT IS NULL THEN (SELECT SHDATA FROM ICM699M WHERE SHMACPKR=A5MACPKR AND SHTYPE='M3-Res-out' AND SHSOURCE='CloseShipmentCoChargeAPI' ORDER BY SHDT DESC, SHTIME DESC FETCH FIRST 1 ROWS ONLY) ELSE '' END AS REASON,
|
||||
A1SHCURR,
|
||||
CASE
|
||||
WHEN (SELECT A4SHIPTYPE FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) = 'LTL'
|
||||
THEN (SELECT A4RATETCP FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) * ".(100.00 - Config::get('arrays.misc.discountCarrierRateForCustomerPriceLTL'))/100 ."
|
||||
ELSE (SELECT A4RATETCP FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) * ".(100.00 - Config::get('arrays.misc.discountCarrierRateForCustomerPriceParcel'))/100 ."
|
||||
END AS FREIGHT
|
||||
FROM ICM688M2
|
||||
LEFT JOIN ICM699M ON SHMACPKR=A5MACPKR AND SHTYPE='M3-Res-out' AND SHDATA LIKE 'Success%' AND SHSOURCE='CloseShipmentCoChargeAPI'
|
||||
LEFT JOIN ICM666M ON A1DELNO=A5MACPKR AND A1ONO=A5ONO AND A1PKLN=A5BRADLN
|
||||
LEFT JOIN ICM688M1 ON A4MACPKR=A5MACPKR
|
||||
WHERE A5MACPKR IN (
|
||||
SELECT DISTINCT AYMACPKR
|
||||
FROM ICM695M1
|
||||
WHERE AYSTATUS IN ('Z','z') AND AYAPR8N002 BETWEEN $reportDate AND $toreportDate
|
||||
)
|
||||
AND A5CO=$COMPANY AND A5WHS=$WHS AND A5PLANT=$PLANT";
|
||||
|
||||
$ICM688M2 = DB::connection(config('m3.connection', 'pgsql'))
|
||||
->select($selectContent);
|
||||
|
||||
$newItem = ["DATECLOSED" => 'Close Date',"A5MACPKR" => 'Delivery #', "A5ONO" => 'Order #',
|
||||
"A4OFSTRM" => 'Terms',"WEIGHT" => 'Weight',"A4SCAC" => 'Carrier',"A4SHIPTYPE" => 'Mode (Parcel, Air, TL or LTL)',
|
||||
"A4REFORD" => 'Order Type',"A5PART" => 'Part #',"A5RSVQTY" => 'Reserved',
|
||||
"A5PACKED" => 'Packed',"CALCULATED_COLUMN" => 'Back Order Qty',"ANOTHER_CALCULATED_COLUMN" => 'Value Packed $',"A4SHSHNM" => 'Customer name',
|
||||
"REASON" => 'Failure Reason','A1SHCURR'=> 'Currency Code','FREIGHT'=> 'Freight'];
|
||||
$ICM688M2Col = collect($ICM688M2);
|
||||
$ICM688M2Col->prepend($newItem);
|
||||
// dd($ICM688M2Col);
|
||||
|
||||
# Count records before exporting to excel : Max 20K records are allowed
|
||||
$ICM688M2Count = $ICM688M2Col->count();
|
||||
# Set Max allowed records
|
||||
$maxRecords = Config::get('arrays.maxRecCL');
|
||||
if ($ICM688M2Count>$maxRecords) {
|
||||
return redirect()->back()->withInput()->with('message', 'Maximum allowed records for Excel Download is: '.number_format($maxRecords).
|
||||
' current records: '.number_format($ICM688M2Count) . ' , change your search criteria.');
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
$ICM688M2Col = "";
|
||||
}
|
||||
# Download Excel
|
||||
# Add true at the end to include fields names in the Header
|
||||
return app(\Modules\M3\Services\SpreadsheetExport::class)->download($ICM688M2Col, 'Closedorderlinesreport_'.$reportDateWD.'-'.$toreportDateWD.'.xlsx');
|
||||
// return $ICM688M2Col->downloadExcel('Closedorderlinesreport_'.$reportDateWD.'-'.$toreportDateWD.'.csv',\Maatwebsite\Excel\Excel::CSV,false);
|
||||
}
|
||||
catch (\Throwable $th) {
|
||||
Log::error($th);
|
||||
}
|
||||
}
|
||||
|
||||
public static function StoreExcelToDisk(Request $request){
|
||||
ini_set('max_execution_time', Config::get('arrays.PHPTimeOutCL'));
|
||||
ini_set('max_input_time', Config::get('arrays.PHPTimeOutCL'));
|
||||
ini_set('default_socket_timeout', Config::get('arrays.PHPTimeOutCL'));
|
||||
ini_set('memory_limit', '1024M');
|
||||
|
||||
try {
|
||||
$SHUSER = m3_user() !== '' ? Str::upper(trim(m3_user())) : '';
|
||||
// dd($SHUSER);
|
||||
|
||||
if ($SHUSER!='') {
|
||||
# Get User CO & WH from Table ICM428M
|
||||
$ICM428M = DB::connection(config('m3.connection', 'pgsql'))->table('icm428m')
|
||||
->select('R428US','R428CO', 'R428WH','R428PL')
|
||||
->where('R428US','=',$SHUSER)
|
||||
->first();
|
||||
|
||||
$R428US = isset($ICM428M->R428US) ? $ICM428M->R428US : ''; # User
|
||||
$COMPANY = isset($ICM428M->R428CO) ? $ICM428M->R428CO : ''; # Company
|
||||
$PLANT = isset($ICM428M->R428PL) ? $ICM428M->R428PL : ''; # Plant
|
||||
$WHS = isset($ICM428M->R428WH) ? $ICM428M->R428WH : ''; # WareHouse
|
||||
}
|
||||
|
||||
# Warehouse Table
|
||||
$IC670M = DB::connection(config('m3.connection', 'pgsql'))->table('ic670m')->get();
|
||||
|
||||
# Get URL PARAMS
|
||||
$urlParams = count($request->all())>0 ? $request->all() : '';
|
||||
// dd($urlParams);
|
||||
$reportDate = isset($urlParams["REPORTDATE"]) ? \DateTime::createFromFormat('Y-m-d', trim($urlParams["REPORTDATE"]))->format('Ymd') : today()->format('Ymd');
|
||||
$toreportDate = isset($urlParams["TOREPORTDATE"]) ? \DateTime::createFromFormat('Y-m-d', trim($urlParams["TOREPORTDATE"]))->format('Ymd') : today()->format('Ymd');
|
||||
// dump($reportDate);
|
||||
// dd($toreportDate);
|
||||
$reportDateWD = isset($urlParams["REPORTDATE"]) ? trim($urlParams["REPORTDATE"]) : today()->format('Y-m-d');
|
||||
$toreportDateWD = isset($urlParams["TOREPORTDATE"]) ? trim($urlParams["TOREPORTDATE"]) : today()->format('Y-m-d');
|
||||
|
||||
$WHDDA = $COMPANY.$PLANT.$WHS;
|
||||
// dump($WHDDA);
|
||||
if($reportDate!='' && $COMPANY!='' && $WHS!='' && $PLANT!=''){
|
||||
# Case 729: Add Currency code A1SHCURR FROM ICM666M
|
||||
$ICM688M2 = DB::connection(config('m3.connection', 'pgsql'))
|
||||
->select("
|
||||
SELECT (SHDT || ' ' || SHTIME) AS DATECLOSED, A5MACPKR, A5ONO,
|
||||
A4OFSTRM,
|
||||
A5PMPWHT*A5PACKED AS WEIGHT,
|
||||
A4SCAC,
|
||||
A4SHIPTYPE,
|
||||
(SELECT A4REFORD FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) AS A4REFORD,
|
||||
A5PART, A5RSVQTY, A5PACKED, A5RSVQTY - A5PACKED AS CALCULATED_COLUMN,
|
||||
A5SLUNPR * A5PACKED AS ANOTHER_CALCULATED_COLUMN,
|
||||
(SELECT A4SHSHNM FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) AS A4SHSHNM ,
|
||||
CASE WHEN SHDT IS NULL THEN (SELECT SHDATA FROM ICM699M WHERE SHMACPKR=A5MACPKR AND SHTYPE='M3-Res-out' AND SHSOURCE='CloseShipmentCoChargeAPI' ORDER BY SHDT DESC, SHTIME DESC FETCH FIRST 1 ROWS ONLY) ELSE '' END AS REASON,
|
||||
A1SHCURR,
|
||||
CASE
|
||||
WHEN (SELECT A4SHIPTYPE FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) = 'LTL'
|
||||
THEN (SELECT A4RATETCP FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) * ".(100.00 - Config::get('arrays.misc.discountCarrierRateForCustomerPriceLTL'))/100 ."
|
||||
ELSE (SELECT A4RATETCP FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) * ".(100.00 - Config::get('arrays.misc.discountCarrierRateForCustomerPriceParcel'))/100 ."
|
||||
END AS FREIGHT
|
||||
FROM ICM688M2
|
||||
LEFT JOIN ICM699M ON SHMACPKR=A5MACPKR AND SHTYPE='M3-Res-out' AND SHDATA LIKE 'Success%' AND SHSOURCE='CloseShipmentCoChargeAPI'
|
||||
LEFT JOIN ICM666M ON A1DELNO=A5MACPKR AND A1ONO=A5ONO AND A1PKLN=A5BRADLN
|
||||
LEFT JOIN ICM688M1 ON A4MACPKR=A5MACPKR
|
||||
WHERE A5MACPKR IN (
|
||||
SELECT DISTINCT AYMACPKR
|
||||
FROM ICM695M1
|
||||
WHERE AYSTATUS IN ('Z','z') AND AYAPR8N002 BETWEEN $reportDate AND $toreportDate
|
||||
)
|
||||
AND A5CO=$COMPANY AND A5WHS=$WHS AND A5PLANT=$PLANT
|
||||
");
|
||||
|
||||
$newItem = ["DATECLOSED" => 'Close Date',"A5MACPKR" => 'Delivery #', "A5ONO" => 'Order #',
|
||||
"A4OFSTRM" => 'Terms',"WEIGHT" => 'Weight',"A4SCAC" => 'Carrier',"A4SHIPTYPE" => 'Mode (Parcel, Air, TL or LTL)',
|
||||
"A4REFORD" => 'Order Type',"A5PART" => 'Part #',"A5RSVQTY" => 'Reserved',
|
||||
"A5PACKED" => 'Packed',"CALCULATED_COLUMN" => 'Back Order Qty',"ANOTHER_CALCULATED_COLUMN" => 'Value Packed $',"A4SHSHNM" => 'Customer name',
|
||||
"REASON" => 'Failure Reason','A1SHCURR'=> 'Currency Code','FREIGHT'=> 'Freight'];
|
||||
$ICM688M2Col = collect($ICM688M2);
|
||||
$ICM688M2Col->prepend($newItem);
|
||||
// dd($ICM688M2Col);
|
||||
|
||||
# Count records before exporting to excel : Max 20K records are allowed
|
||||
$ICM688M2Count = $ICM688M2Col->count();
|
||||
# Set Max allowed records
|
||||
$maxRecords = Config::get('arrays.maxRecCL');
|
||||
if ($ICM688M2Count>$maxRecords) {
|
||||
return redirect()->back()->withInput()->with('message', 'Maximum allowed records for Excel Download is: '.number_format($maxRecords).
|
||||
' current records: '.number_format($ICM688M2Count) . ' , change your search criteria.');
|
||||
}
|
||||
}
|
||||
else{
|
||||
$ICM688M2Col = "";
|
||||
}
|
||||
|
||||
if ($WHS == '321') {
|
||||
$prevMonthFile = 'Closedorderlinesreport_'.$reportDateWD.'-'.$toreportDateWD.'.xlsx';
|
||||
}
|
||||
else{
|
||||
$prevMonthFile = $WHS.'/Closedorderlinesreport_'.$reportDateWD.'-'.$toreportDateWD.'-'.$WHS.'.xlsx';
|
||||
}
|
||||
|
||||
# MAK Store the File to Storage
|
||||
app(\Modules\M3\Services\SpreadsheetExport::class)->store($ICM688M2Col, $prevMonthFile, 'publicCL');
|
||||
|
||||
// $ICM688M2Col->storeExcel('Closedorderlinesreport_'.$reportDateWD.'-'.$toreportDateWD.'.csv', 'publicCL',\Maatwebsite\Excel\Excel::CSV);
|
||||
|
||||
// $ICM688M2Col->storeExcel('Closedorderlinesreport_'.$reportDateWD.'-'.$toreportDateWD.'.ods', 'publicCL',\Maatwebsite\Excel\Excel::ODS);
|
||||
|
||||
// dump('Done Saving Excel...');
|
||||
return back();
|
||||
}
|
||||
catch (\Throwable $th) {
|
||||
Log::error($th);
|
||||
}
|
||||
}
|
||||
|
||||
# Download File
|
||||
public static function downloadFiles(Request $request){
|
||||
// dd($request->all());
|
||||
$fileName = $request->filename;
|
||||
if (Storage::disk('publicCL')->exists($fileName)) {
|
||||
# File exists, retrieve content or URL
|
||||
// $content = Storage::disk('publicCL')->get($fileName);
|
||||
$fileUrl = Storage::disk('publicCL')->url($fileName);
|
||||
// dd($fileUrl);
|
||||
$fileNameOnly = strpos($fileName, '/')!= false ? substr($fileName, strpos($fileName, '/') + 1) : $fileName;
|
||||
# Download the file
|
||||
return Storage::disk('publicCL')->download($fileName, $fileNameOnly);
|
||||
} else {
|
||||
// Download the file (use code below)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use DB;
|
||||
use Config;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Modules\M3\Models\ICM658M;
|
||||
use Datatables;
|
||||
|
||||
class ReplenishSettingsController extends Controller
|
||||
{
|
||||
|
||||
public static function index(Request $request)
|
||||
{
|
||||
# Replenishment Table
|
||||
// $REFCAT658 = DB::connection(config('m3.connection', 'pgsql'))->table('icm658m')->get();
|
||||
# Warehouse Table
|
||||
// $IC670M = DB::connection(config('m3.connection', 'pgsql'))->table('ic670m')->get();
|
||||
|
||||
# Get Logged user Id
|
||||
$userId = m3_user() !== '' ? strtoupper(m3_user()) : '' ;
|
||||
// $userId = 'E1135818'; // Brad : E1135818 Malak : E2011812 ACOM_PDF
|
||||
$connection = config('m3.connection', 'pgsql');
|
||||
$ICM428M = \Illuminate\Support\Facades\Schema::connection($connection)->hasTable('icm428m')
|
||||
? DB::connection($connection)->table('icm428m')->where('R428US',$userId)->where('R428STS','A')->first()
|
||||
: null;
|
||||
|
||||
$userCO = isset($ICM428M->R428CO) ? $ICM428M->R428CO : '';
|
||||
$userPL = isset($ICM428M->R428PL) ? $ICM428M->R428PL : '';
|
||||
$userWH = isset($ICM428M->R428WH) ? $ICM428M->R428WH : '' ;
|
||||
|
||||
if ($userCO!='') {
|
||||
# Warehouse Table
|
||||
$IC670M = \Illuminate\Support\Facades\Schema::connection($connection)->hasTable('ic670m')
|
||||
? DB::connection($connection)->table('ic670m')
|
||||
->where('WDCO',$userCO)
|
||||
->where('WDPL',$userPL)
|
||||
->where('WDWHS',$userWH)
|
||||
->get()
|
||||
: [];
|
||||
}
|
||||
else{
|
||||
// $REFCAT658 =[];
|
||||
$IC670M =[];
|
||||
}
|
||||
|
||||
// $sqlstmt="SELECT t1.REFKEY,t2.FULLID ,t2.*
|
||||
// FROM PRDAT.REFERPS t1 LEFT JOIN ( SELECT R658CO,R658PL,R658WH,R658LC,R658PN,R658MQ,R658RQ,R658TL,R658RMQ,
|
||||
// TRIM(R658WH)||TRIM(R658LC)||TRIM(R658PN) AS FULLID FROM EWOBJTST.ICM658M
|
||||
// ) t2 ON t1.REFKEY = t2.FULLID WHERE t1.REFCAT = '658'";
|
||||
// $REFCAT658 = DB::connection(config('m3.connection', 'pgsql'))->select($sqlstmt);
|
||||
// dd($REFCAT658);
|
||||
|
||||
return view('m3::liberty-theme.pages.ReplenishSettings', compact('IC670M'));
|
||||
// 'REFCAT658',
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
// dd( $request->all() );
|
||||
|
||||
$formInputs = $request->all();
|
||||
$formInputs = array_filter($formInputs);
|
||||
unset($formInputs["_token"]);
|
||||
|
||||
$formInputs['R658IZLCF'] = isset($formInputs['R658IZLCF']) ? $formInputs['R658IZLCF'] : '0';
|
||||
// dd($formInputs);
|
||||
|
||||
$ICM658MINS = ICM658M::insert($formInputs);
|
||||
// dd($ICM658MINS);
|
||||
return redirect()->route('m3.replenishmentSettings.index');
|
||||
}
|
||||
|
||||
public function update(Request $request)
|
||||
{
|
||||
// dd($request->all());
|
||||
$R658PN = (trim($request->R658PN) ?? trim($request->R658PN)) != null ? trim($request->R658PN) : "";
|
||||
$R658CO = (trim($request->R658CO) ?? trim($request->R658CO)) != null ? trim($request->R658CO) : "";
|
||||
$R658PL = (trim($request->R658PL) ?? trim($request->R658PL)) != null ? trim($request->R658PL) : "";
|
||||
$R658WH = (trim($request->R658WH) ?? trim($request->R658WH)) != null ? trim($request->R658WH) : "";
|
||||
$R658MQ = trim($request->R658MQ);
|
||||
$R658RQ = trim($request->R658RQ);
|
||||
$R658RMQ = trim($request->R658RMQ);
|
||||
$R658TL = trim($request->R658TL);
|
||||
$R658IZLCF = (trim($request->R658IZLCF) ?? trim($request->R658IZLCF)) != null ? trim($request->R658IZLCF) : "0";
|
||||
|
||||
DB::connection(config('m3.connection', 'pgsql'))->table('icm658m')
|
||||
->where('R658PN', $R658PN)
|
||||
->where('R658CO', $R658CO)
|
||||
->where('R658PL', $R658PL)
|
||||
->where('R658WH', $R658WH)
|
||||
->update([ 'R658MQ'=>$R658MQ,'R658RQ'=>$R658RQ,'R658RMQ'=>$R658RMQ,'R658TL'=>$R658TL,'R658IZLCF'=>$R658IZLCF ]);
|
||||
|
||||
return redirect()->route('m3.replenishmentSettings.index');
|
||||
}
|
||||
|
||||
public function deleteRec(Request $request)
|
||||
{
|
||||
// dd( $request->all() );
|
||||
$R658PN = trim($request->R658PN);
|
||||
$R658CO = trim($request->R658CO);
|
||||
$R658LC = trim($request->R658LC);
|
||||
$R658PL = trim($request->R658PL);
|
||||
$R658WH = trim($request->R658WH);
|
||||
|
||||
$deleteRecord = DB::connection(config('m3.connection', 'pgsql'))->table('icm658m')
|
||||
->where('R658PN', $R658PN)
|
||||
->where('R658CO', $R658CO)
|
||||
->where('R658LC', $R658LC)
|
||||
->where('R658PL', $R658PL)
|
||||
->where('R658WH', $R658WH)
|
||||
->delete();
|
||||
|
||||
return response()->json(['success'=>'Record Deleted']);
|
||||
}
|
||||
|
||||
public function checkRecExit(Request $request)
|
||||
{
|
||||
// dd( $request->all() );
|
||||
$params = array();
|
||||
parse_str($request['data'], $params);
|
||||
$paramsObj = (object)$params;
|
||||
// dd($paramsObj);
|
||||
|
||||
$R658PN = trim($paramsObj->R658PN);
|
||||
$R658CO = trim($paramsObj->R658CO);
|
||||
$R658LC = trim($paramsObj->R658LC);
|
||||
$R658PL = trim($paramsObj->R658PL);
|
||||
$R658WH = trim($paramsObj->R658WH);
|
||||
|
||||
$recordExistSQL = DB::connection(config('m3.connection', 'pgsql'))->table('icm658m')
|
||||
->where('R658PN', $R658PN)
|
||||
->where('R658CO', $R658CO)
|
||||
->where('R658LC', $R658LC)
|
||||
->where('R658PL', $R658PL)
|
||||
->where('R658WH', $R658WH)
|
||||
->first();
|
||||
// dd($recordExists);
|
||||
$recordExists = $recordExistSQL == null ? true : false;
|
||||
|
||||
return response()->json(['recordExists'=>$recordExists]);
|
||||
}
|
||||
|
||||
public function datatables(Request $request){
|
||||
# Replenishment Table
|
||||
// $REFCAT658 = DB::connection(config('m3.connection', 'pgsql'))->table('icm658m')->get();
|
||||
# Warehouse Table
|
||||
// $IC670M = DB::connection(config('m3.connection', 'pgsql'))->table('ic670m')->get();
|
||||
|
||||
# Get Logged user Id
|
||||
$userId = m3_user() !== '' ? strtoupper(m3_user()) : '' ;
|
||||
// $userId = 'E1135818'; // Brad : E1135818 Malak : E2011812 ACOM_PDF
|
||||
$connection = config('m3.connection', 'pgsql');
|
||||
$ICM428M = \Illuminate\Support\Facades\Schema::connection($connection)->hasTable('icm428m')
|
||||
? DB::connection($connection)->table('icm428m')->where('R428US',$userId)->where('R428STS','A')->first()
|
||||
: null;
|
||||
|
||||
$userCO = isset($ICM428M->R428CO) ? $ICM428M->R428CO : '';
|
||||
$userPL = isset($ICM428M->R428PL) ? $ICM428M->R428PL : '';
|
||||
$userWH = isset($ICM428M->R428WH) ? $ICM428M->R428WH : '' ;
|
||||
|
||||
if ($userCO!='') {
|
||||
# Replenishment Table
|
||||
$REFCAT658 = DB::connection(config('m3.connection', 'pgsql'))->table('icm658m')
|
||||
->select('*')
|
||||
->where('R658CO',$userCO)
|
||||
->where('R658PL',$userPL)
|
||||
->where('R658WH',$userWH)
|
||||
->orderBy('R658CO','asc');
|
||||
|
||||
# Warehouse Table
|
||||
// $IC670M = DB::connection(config('m3.connection', 'pgsql'))->table('ic670m')
|
||||
// ->where('WDCO',$userCO)
|
||||
// ->where('WDPL',$userPL)
|
||||
// ->where('WDWHS',$userWH)
|
||||
// ->get();
|
||||
}
|
||||
else{
|
||||
$REFCAT658 =[];
|
||||
// $IC670M =[];
|
||||
}
|
||||
|
||||
// $sqlstmt="SELECT t1.REFKEY,t2.FULLID ,t2.*
|
||||
// FROM PRDAT.REFERPS t1 LEFT JOIN ( SELECT R658CO,R658PL,R658WH,R658LC,R658PN,R658MQ,R658RQ,R658TL,R658RMQ,
|
||||
// TRIM(R658WH)||TRIM(R658LC)||TRIM(R658PN) AS FULLID FROM EWOBJTST.ICM658M
|
||||
// ) t2 ON t1.REFKEY = t2.FULLID WHERE t1.REFCAT = '658'";
|
||||
// $REFCAT658 = DB::connection(config('m3.connection', 'pgsql'))->select($sqlstmt);
|
||||
// dd($REFCAT658);
|
||||
|
||||
// dd( Datatables::of($REFCAT658)->addIndexColumn()->make(true) );
|
||||
|
||||
return Datatables::of($REFCAT658)->addIndexColumn()->make(true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers;
|
||||
|
||||
use Modules\M3\Models\ShipTo;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use DB;
|
||||
use Config;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Datatables;
|
||||
|
||||
class ShipToController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
if ($request->ajax()) {
|
||||
$data = ShipTo::select('*');
|
||||
|
||||
return Datatables::of($data)
|
||||
->addIndexColumn()
|
||||
->addColumn('checkbox', function ($row) {
|
||||
return '';
|
||||
})
|
||||
->addColumn('action', function ($row) {
|
||||
$actionBtn = '<a href="' . url('/ship-to/' . trim($row->AUSHSHZP) . '/' . trim($row->AUSHWHS) . '/edit') . '" class="edit btn btn-primary btn-sm">Edit</a> ';
|
||||
$actionBtn .= '<form method="POST" action="' . url('ship-to/' . urlencode(trim($row->AUSHSHZP)) . '/' . urlencode(trim($row->AUSHWHS))) . '" style="display:inline">';
|
||||
$actionBtn .= csrf_field() . method_field('DELETE');
|
||||
$actionBtn .= '<button type="submit" class="btn btn-danger btn-sm" onclick="return confirm(\'Are you sure?\')">Delete</button></form>';
|
||||
return $actionBtn;
|
||||
})
|
||||
->rawColumns(['checkbox', 'action'])
|
||||
->make(true);
|
||||
}
|
||||
return view('m3::liberty-theme.pages.ship-to.index');
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
# US
|
||||
$USstates = \Modules\M3\Helpers\USStates::all();
|
||||
# CA
|
||||
$CAstates = \Modules\M3\Helpers\CAProvinces::all();
|
||||
|
||||
# All States
|
||||
$states = array_merge($USstates, $CAstates);
|
||||
|
||||
return view('m3::liberty-theme.pages.ship-to.create', compact('states'));
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validated = $request->validate(
|
||||
[
|
||||
'AUSTCN' => 'nullable|max:11',
|
||||
'AUSHSHNM' => 'required|max:36',
|
||||
'AUSHSHA1' => 'required|max:36',
|
||||
'AUSHSHA2' => 'required|max:36',
|
||||
'AUSHSHA3' => 'nullable|max:36',
|
||||
'AUSHSHA4' => 'nullable|max:36',
|
||||
'AUSHSHCI' => 'required|max:20',
|
||||
'AUSHSHST' => 'required|max:2',
|
||||
'AUSHSHZP' => 'required|max:10',
|
||||
'AUSHSHCT' => 'required|max:3',
|
||||
'AUSHWHS' => 'required|max:3'
|
||||
],
|
||||
[
|
||||
'AUSHSHNM.required' => 'Name is required',
|
||||
'AUSHSHA1.required' => 'Address 1 is required',
|
||||
'AUSHSHA2.required' => 'Address 2 is required',
|
||||
'AUSHSHCI.required' => 'City is required',
|
||||
'AUSHSHST.required' => 'State is required',
|
||||
'AUSHSHZP.required' => 'Zip code is required',
|
||||
'AUSHSHCT.required' => 'Country is required',
|
||||
'AUSHWHS.required' => 'Warehouse is required',
|
||||
|
||||
'AUSTCN.max' => 'Customer Number cannot exceed 11 characters',
|
||||
'AUSHSHNM.max' => 'Name cannot exceed 36 characters',
|
||||
'AUSHSHA1.max' => 'Address 1 cannot exceed 36 characters',
|
||||
'AUSHSHA2.max' => 'Address 2 cannot exceed 36 characters',
|
||||
'AUSHSHA3.max' => 'Address 3 cannot exceed 36 characters',
|
||||
'AUSHSHA4.max' => 'Address 4 cannot exceed 36 characters',
|
||||
'AUSHSHCI.max' => 'City cannot exceed 20 characters',
|
||||
'AUSHSHST.max' => 'State cannot exceed 2 characters',
|
||||
'AUSHSHZP.max' => 'Zip code cannot exceed 10 characters',
|
||||
'AUSHSHCT.max' => 'Country cannot exceed 3 characters',
|
||||
'AUSHWHS.max' => 'Warehouse cannot exceed 3 characters'
|
||||
]
|
||||
);
|
||||
$validated['AUSTCN'] = $validated['AUSTCN'] ?? ' ';
|
||||
|
||||
$model = new ShipTo();
|
||||
$model->fill($validated);
|
||||
$success = $model->save();
|
||||
// ShipTo::create($validated);
|
||||
if ($success) {
|
||||
return redirect()->route('m3.ship-to.index')->with('success', 'Record created successfully.');
|
||||
} else {
|
||||
return redirect()->back()
|
||||
->withErrors(['unique' => 'The combination of ZipCode and Warehouse must be unique.'])
|
||||
->withInput();
|
||||
}
|
||||
}
|
||||
|
||||
public function edit($aushshzp, $aushwhs)
|
||||
{
|
||||
# US
|
||||
$USstates = \Modules\M3\Helpers\USStates::all();
|
||||
# CA
|
||||
$CAstates = \Modules\M3\Helpers\CAProvinces::all();
|
||||
|
||||
# All States
|
||||
$states = array_merge($USstates, $CAstates);
|
||||
|
||||
$shipTo = ShipTo::where('AUSHSHZP', $aushshzp)
|
||||
->where('AUSHWHS', $aushwhs)
|
||||
->firstOrFail();
|
||||
return view('m3::liberty-theme.pages.ship-to.edit', compact('shipTo', 'states'));
|
||||
}
|
||||
|
||||
public function update(Request $request, $aushshzp, $aushwhs)
|
||||
{
|
||||
$validated = array_map(function ($value) {
|
||||
return $value === null ? '' : $value;
|
||||
}, $request->validate(
|
||||
[
|
||||
'AUSTCN' => 'nullable|string|max:11',
|
||||
'AUSHSHNM' => 'required|max:36',
|
||||
'AUSHSHA1' => 'required|max:36',
|
||||
'AUSHSHA2' => 'required|max:36',
|
||||
'AUSHSHA3' => 'nullable|string|max:36',
|
||||
'AUSHSHA4' => 'nullable|string|max:36',
|
||||
'AUSHSHCI' => 'required|max:20',
|
||||
'AUSHSHST' => 'required|max:2',
|
||||
'AUSHSHCT' => 'required|max:3'
|
||||
],
|
||||
[
|
||||
'AUSHSHNM.required' => 'Name is required',
|
||||
'AUSHSHA1.required' => 'Address 1 is required',
|
||||
'AUSHSHA2.required' => 'Address 2 is required',
|
||||
'AUSHSHCI.required' => 'City is required',
|
||||
'AUSHSHST.required' => 'State is required',
|
||||
'AUSHSHZP.required' => 'Zip code is required',
|
||||
'AUSHSHCT.required' => 'Country is required',
|
||||
'AUSHWHS.required' => 'Warehouse is required',
|
||||
|
||||
'AUSTCN.max' => 'Customer Number cannot exceed 11 characters',
|
||||
'AUSHSHNM.max' => 'Name cannot exceed 36 characters',
|
||||
'AUSHSHA1.max' => 'Address 1 cannot exceed 36 characters',
|
||||
'AUSHSHA2.max' => 'Address 2 cannot exceed 36 characters',
|
||||
'AUSHSHA3.max' => 'Address 3 cannot exceed 36 characters',
|
||||
'AUSHSHA4.max' => 'Address 4 cannot exceed 36 characters',
|
||||
'AUSHSHCI.max' => 'City cannot exceed 20 characters',
|
||||
'AUSHSHST.max' => 'State cannot exceed 2 characters',
|
||||
'AUSHSHZP.max' => 'Zip code cannot exceed 10 characters',
|
||||
'AUSHSHCT.max' => 'Country cannot exceed 3 characters',
|
||||
'AUSHWHS.max' => 'Warehouse cannot exceed 3 characters'
|
||||
]
|
||||
));
|
||||
|
||||
$updated = ShipTo::where('AUSHSHZP', $aushshzp)
|
||||
->where('AUSHWHS', $aushwhs)
|
||||
->update($validated);
|
||||
|
||||
if ($updated) {
|
||||
return redirect()->route('m3.ship-to.index')->with('success', 'Record updated successfully.');
|
||||
} else {
|
||||
return redirect()->route('m3.ship-to.index')->with('error', 'Record could not be updated.');
|
||||
}
|
||||
}
|
||||
|
||||
public function destroy($aushshzp, $aushwhs)
|
||||
{
|
||||
$deleted = ShipTo::where('AUSHSHZP', $aushshzp)
|
||||
->where('AUSHWHS', $aushwhs)
|
||||
->delete();
|
||||
|
||||
if ($deleted) {
|
||||
return redirect()->route('m3.ship-to.index')->with('success', 'Record deleted successfully.');
|
||||
} else {
|
||||
return redirect()->route('m3.ship-to.index')->with('error', 'Record not found or could not be deleted.');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use DB;
|
||||
use Config;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Str;
|
||||
use Log;
|
||||
use Excel;
|
||||
use Storage;
|
||||
|
||||
class WhsPerfMetrics extends Controller
|
||||
{
|
||||
public static function index(Request $request){
|
||||
try {
|
||||
$SHUSER = m3_user() !== '' ? Str::upper(trim(m3_user())) : '';
|
||||
// dd($SHUSER);
|
||||
|
||||
if ($SHUSER!='') {
|
||||
# Get User CO & WH from Table ICM428M
|
||||
$ICM428M = DB::connection(config('m3.connection', 'pgsql'))->table('icm428m')
|
||||
->select('R428US','R428CO', 'R428WH','R428PL')
|
||||
->where('R428US','=',$SHUSER)
|
||||
->first();
|
||||
|
||||
$R428US = isset($ICM428M->R428US) ? $ICM428M->R428US : ''; # User
|
||||
$COMPANY = isset($ICM428M->R428CO) ? $ICM428M->R428CO : '110'; # Company
|
||||
$PLANT = isset($ICM428M->R428PL) ? $ICM428M->R428PL : '144'; # Plant
|
||||
$WHS = isset($ICM428M->R428WH) ? $ICM428M->R428WH : '322'; # WareHouse
|
||||
}
|
||||
|
||||
# Warehouse Table
|
||||
$IC670M = DB::connection(config('m3.connection', 'pgsql'))->table('ic670m')->get();
|
||||
|
||||
# Get URL PARAMS
|
||||
$urlParams = count($request->all())>0 ? $request->all() : '';
|
||||
// dump($urlParams);
|
||||
$REPORTDATEDisp = isset($urlParams["REPORTDATEDisp"]) ? \DateTime::createFromFormat('Y-m-d', trim($urlParams["REPORTDATEDisp"]))->format('Ymd') : today()->format('Ymd');
|
||||
|
||||
$WHDDA = $COMPANY.$PLANT.$WHS;
|
||||
// dump($WHDDA);
|
||||
if($REPORTDATEDisp!='' && $COMPANY!='' && $WHS!='' && $PLANT!=''){
|
||||
# Case 729: Add Currency code A1SHCURR FROM ICM666M
|
||||
$selectContent = "
|
||||
SELECT A5MACPKR, A5ONO,
|
||||
(SELECT A4REFORD FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) AS A4REFORD,
|
||||
A5PART, A5RSVQTY, A5PACKED, A5RSVQTY - A5PACKED AS CALCULATED_COLUMN,
|
||||
A5SLUNPR * A5PACKED AS ANOTHER_CALCULATED_COLUMN,
|
||||
(SELECT A4SHSHNM FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) AS A4SHSHNM ,
|
||||
SHDT, SHTIME,
|
||||
CASE WHEN SHDT IS NULL THEN (SELECT SHDATA FROM ICM699M WHERE SHMACPKR=A5MACPKR AND SHTYPE='M3-Res-out' AND SHSOURCE='CloseShipmentCoChargeAPI' ORDER BY SHDT DESC, SHTIME DESC FETCH FIRST 1 ROWS ONLY) ELSE '' END AS REASON,
|
||||
A1SHCURR,
|
||||
CASE
|
||||
WHEN (SELECT A4SHIPTYPE FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) = 'LTL'
|
||||
THEN (SELECT A4RATETCP FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) * ".(100.00 - Config::get('arrays.misc.discountCarrierRateForCustomerPriceLTL'))/100 ."
|
||||
ELSE (SELECT A4RATETCP FROM ICM688M1 WHERE A4MACPKR=A5MACPKR) * ".(100.00 - Config::get('arrays.misc.discountCarrierRateForCustomerPriceParcel') )/100 ."
|
||||
END AS FREIGHT
|
||||
FROM ICM688M2
|
||||
LEFT JOIN ICM699M ON SHMACPKR=A5MACPKR AND SHTYPE='M3-Res-out' AND SHDATA LIKE 'Success%' AND SHSOURCE='CloseShipmentCoChargeAPI'
|
||||
LEFT JOIN ICM666M ON A1DELNO=A5MACPKR AND A1ONO=A5ONO AND A1PKLN=A5BRADLN
|
||||
WHERE A5MACPKR IN (
|
||||
SELECT DISTINCT AYMACPKR
|
||||
FROM ICM695M1
|
||||
WHERE AYSTATUS IN ('Z','z') AND AYAPR8N002 = $REPORTDATEDisp
|
||||
)
|
||||
AND A5CO=$COMPANY AND A5WHS=$WHS AND A5PLANT=$PLANT";
|
||||
// dump($selectContent);
|
||||
|
||||
$ICM688M2 = DB::connection(config('m3.connection', 'pgsql'))
|
||||
->select($selectContent);
|
||||
// dd($ICM688M2);
|
||||
}
|
||||
else{
|
||||
$ICM688M2 = collect();
|
||||
}
|
||||
|
||||
# Get List of Files
|
||||
$allReportsUrls = [];
|
||||
$files = Storage::disk('publicLabels')->allFiles('WhsPerf/'.$WHS);
|
||||
// $whsPerfFile = 'WhsPerf/'.$WHS.'/WhsPerfMetrics_'.$DateToday.'-'.$WHS.'.xlsx';
|
||||
|
||||
foreach ($files as $file) {
|
||||
# Get the file URL (if URL is configured in filesystems.php)
|
||||
$url = Storage::disk('publicLabels')->url($file);
|
||||
$allReportsUrls[$file] = $url;
|
||||
}
|
||||
// dd($allReportsUrls);
|
||||
}
|
||||
catch (\Throwable $th) {
|
||||
Log::error($th);
|
||||
}
|
||||
|
||||
return view('m3::liberty-theme.pages.WhsPerfMetrics',compact('IC670M','WHDDA','COMPANY','PLANT','WHS','allReportsUrls'));
|
||||
}
|
||||
|
||||
|
||||
# Download File
|
||||
public static function downloadFiles(Request $request){
|
||||
// dd($request->all());
|
||||
$fileName = $request->filename;
|
||||
if (Storage::disk('publicLabels')->exists($fileName)) {
|
||||
# File exists, retrieve content or URL
|
||||
$fileUrl = Storage::disk('publicLabels')->url($fileName);
|
||||
$fileNameOnly = basename($fileName);
|
||||
# Download the file
|
||||
return Storage::disk('publicLabels')->download($fileName, $fileNameOnly);
|
||||
} else {
|
||||
// Download the file (use code below)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers;
|
||||
|
||||
class authController extends Controller
|
||||
{
|
||||
public static function logout(){
|
||||
|
||||
return view('m3::liberty-theme.pages.logout');
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use DB;
|
||||
use Config;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Modules\M3\Models\ICM160M;
|
||||
use Modules\M3\Helpers\Helper;
|
||||
|
||||
|
||||
class carrierMaintController extends Controller
|
||||
{
|
||||
|
||||
public static function index(Request $request) {
|
||||
$currentUser = Helper::getUserCOWHSPLT();
|
||||
$UserCO = $currentUser['UserCO'] ?? '';
|
||||
$ICM160M = [];
|
||||
$power_user = [];
|
||||
$schema = \Illuminate\Support\Facades\Schema::connection(config('m3.connection', 'pgsql'));
|
||||
if ($schema->hasTable('icm160m')) {
|
||||
$ICM160M = DB::connection(config('m3.connection', 'pgsql'))->select("
|
||||
select canum, canam, substr(CATPID,1,3) as TwoshipCarrierCode, substr(CATPID,4,1) as ParcelCarrierCode, caspr10A01, caspr1A01
|
||||
from icm160m WHERE CACO=?", [$UserCO]);
|
||||
}
|
||||
if ($schema->hasTable('icm428m')) {
|
||||
$power_user = DB::connection(config('m3.connection', 'pgsql'))->table('icm428m')
|
||||
->select('R428PWRUSR', 'R428CO', 'R428PL', 'R428WH')
|
||||
->where('R428US', strtoUpper(m3_user()))->get()->all();
|
||||
}
|
||||
return view('m3::liberty-theme.pages.carrierMaint', compact('ICM160M','power_user'));
|
||||
|
||||
}
|
||||
|
||||
# Process data from Add modal
|
||||
public static function savecarrierAdd(Request $request) {
|
||||
$currentUser = Helper::getUserCOWHSPLT();
|
||||
$UserCO = $currentUser['UserCO'] ?? '';
|
||||
// $UserWHS = $currentUser['UserWHS'] ?? '';
|
||||
// $UserPL = $currentUser['UserPL'] ?? '';
|
||||
|
||||
# Insert record to ICM160M
|
||||
# Verify record does not already exist in ICM160M
|
||||
if($request->CANUM == NULL) {
|
||||
return "null";
|
||||
}
|
||||
$icm160m=DB::connection(config('m3.connection', 'pgsql'))->select("select count(*) as COUNT1 from ICM160M where CANUM='$request->CANUM' AND CACO='$UserCO'");
|
||||
if($icm160m[0]->COUNT1=="1") {
|
||||
return "exists";
|
||||
} else {
|
||||
$CASPR10A01 = isset($request->CASPR10A01) && $request->CASPR10A01 != NULL ? $request->CASPR10A01 : ' ';
|
||||
$CASPR1A01 = isset($request->CASPR1A01) && $request->CASPR1A01 != NULL ? $request->CASPR1A01 : ' ';
|
||||
|
||||
$data=['CANUM'=>$request->CANUM, 'CANAM'=>$request->CANAM,
|
||||
'CATPID'=>str_pad(substr($request->TWOSHIPCARRIERCODE,0,3),3," ").substr($request->PARCELCARRIERCODE,0,1),
|
||||
'CASPR10A01'=>$CASPR10A01, 'CASPR1A01'=>$CASPR1A01,'CACO'=>$UserCO]; // ,'CAPLNT'=>$UserPL,'CAWHS'=>$UserWHS
|
||||
$insertSQL = DB::connection(config('m3.connection', 'pgsql'))->table('icm160m')->insert($data);
|
||||
if($insertSQL) {
|
||||
return "success";
|
||||
}
|
||||
}
|
||||
}
|
||||
public static function savecarrierAdd2(Request $request) {
|
||||
$currentUser = Helper::getUserCOWHSPLT();
|
||||
$UserCO = $currentUser['UserCO'] ?? '';
|
||||
// $UserWHS = $currentUser['UserWHS'] ?? '';
|
||||
// $UserPL = $currentUser['UserPL'] ?? '';
|
||||
|
||||
# Insert record to ICM160M
|
||||
if($request->CANUM == NULL) {
|
||||
return "null";
|
||||
}
|
||||
|
||||
$CASPR10A01 = isset($request->CASPR10A01) && $request->CASPR10A01 != NULL ? $request->CASPR10A01 : ' ';
|
||||
$CASPR1A01 = isset($request->CASPR1A01) && $request->CASPR1A01 != NULL ? $request->CASPR1A01 : ' ';
|
||||
|
||||
$data=['CANUM'=>$request->CANUM, 'CANAM'=>$request->CANAM, 'CATPID'=>str_pad(substr($request->TWOSHIPCARRIERCODE,0,3),3," ").substr($request->PARCELCARRIERCODE,0,1),
|
||||
'CASPR10A01'=>$CASPR10A01, 'CASPR1A01'=>$CASPR1A01,'CACO'=>$UserCO]; // ,'CAPLNT'=>$UserPL,'CAWHS'=>$UserWHS
|
||||
$insertSQL = DB::connection(config('m3.connection', 'pgsql'))->table('icm160m')->insert($data);
|
||||
if($insertSQL) {
|
||||
return "success";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Process data from Edit modal
|
||||
public static function savecarrierEdit(Request $request) {
|
||||
$currentUser = Helper::getUserCOWHSPLT();
|
||||
$UserCO = $currentUser['UserCO'] ?? '';
|
||||
|
||||
if($request->CANUM == NULL) {
|
||||
return "null";
|
||||
}
|
||||
DB::connection(config('m3.connection', 'pgsql'))->update("update ICM160M
|
||||
set CANAM='$request->CANAM', CATPID='".str_pad(substr($request->TWOSHIPCARRIERCODE,0,3),3," ").substr($request->PARCELCARRIERCODE,0,1)."',
|
||||
CASPR10A01='$request->CASPR10A01', CASPR1A01='$request->CASPR1A01'
|
||||
where CANUM='$request->CANUM' AND CACO='$UserCO'");
|
||||
|
||||
return "success";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers;
|
||||
use DB;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class dashboardController extends Controller
|
||||
{
|
||||
public static function index(){
|
||||
return view('m3::liberty-theme.pages.dashboard');
|
||||
// , compact('data','whs','whs_array','starting','ending')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use DB;
|
||||
use Config;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Str;
|
||||
use Log;
|
||||
|
||||
|
||||
class execSummaryController extends Controller
|
||||
{
|
||||
public static function index(Request $request){
|
||||
$IC670M = collect();
|
||||
$WHDDA = '';
|
||||
$COMPANY = '110';
|
||||
$PLANT = '144';
|
||||
$WHS = '322';
|
||||
|
||||
try {
|
||||
# Ajax Call
|
||||
if ($request->ajax()) {
|
||||
// dump($request->all());
|
||||
$WHDDA = isset($request->WHDDA) ? $request->WHDDA : array();
|
||||
$WHArr = array();
|
||||
foreach ($WHDDA as $key => $WHDDAV) {
|
||||
$CO = substr($WHDDAV, 0, 3);
|
||||
// $R428PL = substr($WHDDAV, 3, 3);
|
||||
$WHArr[] = substr($WHDDAV, 6, 3);
|
||||
}
|
||||
|
||||
$reportPeriod = isset($request->reportPeriod) ? $request->reportPeriod : ''; # monthly , quarter , year , daily
|
||||
# Current
|
||||
$checkSales = isset($request->checkSales) ? $request->checkSales : ''; # on
|
||||
$checkWeight = isset($request->checkWeight) ? $request->checkWeight : ''; # on
|
||||
$checkLines = isset($request->checkLines) ? $request->checkLines : ''; # on
|
||||
|
||||
if(count($WHArr)>0 && $CO!='' && $reportPeriod!=''){
|
||||
switch ($reportPeriod) {
|
||||
case 'year':
|
||||
# Set Dates based on reportPeriod type
|
||||
$firstDay = isset($request->REPORTDATE) ? \DateTime::createFromFormat('Y-m', $request->REPORTDATE) : '';
|
||||
$reportDate = $firstDay->modify('first day of January')->format('Ymd');
|
||||
|
||||
$lastDay = isset($request->TOREPORTDATE) ? \DateTime::createFromFormat('Y-m', trim($request->TOREPORTDATE)) : '';
|
||||
$toreportDate = $lastDay->modify('last day of December')->format('Ymd');
|
||||
|
||||
# Build SQL
|
||||
$selectContent = "with tempfile as (
|
||||
select a5rsvqty,a5packed,a5slunpr*a5packed as dollars,a5lnwght,a5whs,
|
||||
(select max(ayapr8N002) as ayapr8N002 from icm695m1 where a5macpkr=aymacpkr fetch first 1 rows only)
|
||||
from icm688m2 where a5macpkr in (
|
||||
select distinct aymacpkr from icm695m1 where (AYSTATUS in ('Z','z') and ayapr8N002>=$reportDate and ayapr8N002<=$toreportDate )
|
||||
) and a5co='".$CO."' and a5whs in(".implode(",", $WHArr).")
|
||||
)
|
||||
select substr(ayapr8N002,1,4) as years,count(*) as lines,sum(a5rsvqty) as reserveqty,sum(a5packed) as packed,sum(a5lnwght*a5packed/a5rsvqty) as weight,sum(dollars) as dollars,a5whs as whs from tempfile
|
||||
group by substr(ayapr8N002,1,4),a5whs order by 1 ";
|
||||
break;
|
||||
|
||||
case 'quarter':
|
||||
# Set Dates based on reportPeriod type
|
||||
$firstDay = isset($request->REPORTDATE) ? \DateTime::createFromFormat('Y-m', $request->REPORTDATE) : '';
|
||||
$reportDate = $firstDay->modify('first day of January')->format('Ymd');
|
||||
|
||||
$lastDay = isset($request->TOREPORTDATE) ? \DateTime::createFromFormat('Y-m', trim($request->TOREPORTDATE)) : '';
|
||||
$toreportDate = $lastDay->modify('last day of December')->format('Ymd');
|
||||
|
||||
# Build SQL
|
||||
$selectContent = "with tempfile as (
|
||||
select a5rsvqty,a5packed,a5slunpr*a5packed as dollars,a5lnwght,a5whs,
|
||||
(select max(ayapr8N002) as ayapr8N002 from icm695m1 where a5macpkr=aymacpkr fetch first 1 rows only)
|
||||
from icm688m2 where a5macpkr in (
|
||||
select distinct aymacpkr from icm695m1 where (AYSTATUS in ('Z','z') and ayapr8N002>=$reportDate and ayapr8N002<=$toreportDate )
|
||||
) and a5co='".$CO."' and a5whs in (".implode(",", $WHArr).")
|
||||
)
|
||||
select substr(ayapr8N002,3,2) ||'-' || 'Q' || EXTRACT(QUARTER FROM TO_DATE(CAST(ayapr8n002 AS TEXT),'YYYYMMDD')) as years,count(*) as lines,
|
||||
sum(a5rsvqty) as reserveqty, sum(a5packed) as packed,sum (a5lnwght*a5packed/a5rsvqty) as weight,sum(dollars) as dollars, a5whs as whs
|
||||
from tempfile
|
||||
group by substr(ayapr8N002,3,2) ||'-' || 'Q' || EXTRACT(QUARTER FROM TO_DATE(CAST(ayapr8n002 AS TEXT),'YYYYMMDD')),a5whs order by 1 ";
|
||||
break;
|
||||
|
||||
case 'monthly':
|
||||
# Set Dates based on reportPeriod type
|
||||
$firstDay = isset($request->REPORTDATE) ? \DateTime::createFromFormat('Y-m', $request->REPORTDATE) : '';
|
||||
$reportDate = $firstDay->modify('first day of this month')->format('Ymd');
|
||||
|
||||
$lastDay = isset($request->TOREPORTDATE) ? \DateTime::createFromFormat('Y-m', trim($request->TOREPORTDATE)) : '';
|
||||
$toreportDate =$lastDay->modify('last day of this month')->format('Ymd');
|
||||
|
||||
# Build SQL
|
||||
$selectContent = "with tempfile as (
|
||||
select a5rsvqty,a5packed,a5slunpr*a5packed as dollars,a5lnwght,a5whs,
|
||||
(select max(ayapr8N002) as ayapr8N002 from icm695m1 where a5macpkr=aymacpkr fetch first 1 rows only)
|
||||
from icm688m2 where a5macpkr in (
|
||||
select distinct aymacpkr from icm695m1 where (AYSTATUS in ('Z','z') and ayapr8N002>=$reportDate and ayapr8N002<=$toreportDate )
|
||||
) and a5co='".$CO."' and a5whs in (".implode(",", $WHArr).")
|
||||
)
|
||||
select substr(ayapr8N002,1,4) || '-' || substr(ayapr8N002,5,2) as years,count(*) as lines,sum(a5rsvqty) as reserveqty,sum(a5packed) as packed,
|
||||
sum(a5lnwght*a5packed/a5rsvqty) as weight,sum(dollars) as dollars, a5whs as whs
|
||||
from tempfile
|
||||
group by substr(ayapr8N002,1,4) || '-' || substr(ayapr8N002,5,2),a5whs order by 1 ";
|
||||
break;
|
||||
|
||||
case 'custom':
|
||||
# Set Dates based on reportPeriod type
|
||||
$firstDay = isset($request->REPORTDATE) ? \DateTime::createFromFormat('Y-m', $request->REPORTDATE) : '';
|
||||
$reportDate = $firstDay->modify('first day of this month')->format('Ymd');
|
||||
|
||||
$toreportDate = $firstDay->modify('last day of this month')->format('Ymd');
|
||||
// $lastDay = isset($request->TOREPORTDATE) ? \DateTime::createFromFormat('Y-m', trim($request->TOREPORTDATE)) : '';
|
||||
// $toreportDate =$lastDay->modify('last day of this month')->format('Ymd');
|
||||
|
||||
# Build SQL
|
||||
$selectContent = "with tempfile as (
|
||||
select a5rsvqty,a5packed,a5slunpr*a5packed as dollars,a5lnwght,a5whs,
|
||||
(select max(ayapr8N002) as ayapr8N002 from icm695m1 where a5macpkr=aymacpkr fetch first 1 rows only)
|
||||
from icm688m2 where a5macpkr in (
|
||||
select distinct aymacpkr from icm695m1 where (AYSTATUS in ('Z','z') and ayapr8N002>=$reportDate and ayapr8N002<=$toreportDate )
|
||||
) and a5co='".$CO."' and a5whs in (".implode(",", $WHArr).")
|
||||
)
|
||||
select substr(ayapr8N002,7,2) as years,count(*) as lines,sum(a5rsvqty) as reserveqty,sum(a5packed) as packed,
|
||||
sum(a5lnwght*a5packed/a5rsvqty) as weight, sum(dollars) as dollars, a5whs as whs
|
||||
from tempfile
|
||||
group by substr(ayapr8N002,7,2),a5whs order by 1 ";
|
||||
break;
|
||||
|
||||
default:
|
||||
$selectContent = "";
|
||||
break;
|
||||
}
|
||||
// dump($reportDate);
|
||||
// dump($toreportDate);
|
||||
// dump($selectContent);
|
||||
|
||||
$execSummaryRes = DB::connection(config('m3.connection', 'pgsql'))->select($selectContent);
|
||||
}
|
||||
else{
|
||||
$execSummaryRes = collect();
|
||||
}
|
||||
// dump($execSummaryRes);
|
||||
|
||||
return response()->json(['success'=>true,'reportPeriod'=> $reportPeriod, 'result'=>$execSummaryRes, 'checkSales'=>$checkSales,
|
||||
'checkWeight'=>$checkWeight, 'checkLines'=>$checkLines]);
|
||||
}
|
||||
|
||||
# Init Page
|
||||
$SHUSER = m3_user() !== '' ? Str::upper(trim(m3_user())) : '';
|
||||
// dd($SHUSER);
|
||||
if ($SHUSER!='') {
|
||||
# Get User CO & WH from Table ICM428M
|
||||
$ICM428M = DB::connection(config('m3.connection', 'pgsql'))->table('icm428m')
|
||||
->select('R428US','R428CO', 'R428WH','R428PL')
|
||||
->where('R428US','=',$SHUSER)
|
||||
->first();
|
||||
|
||||
$R428US = isset($ICM428M->R428US) ? $ICM428M->R428US : ''; # User
|
||||
$COMPANY = isset($ICM428M->R428CO) ? $ICM428M->R428CO : '110'; # Company
|
||||
$PLANT = isset($ICM428M->R428PL) ? $ICM428M->R428PL : '144'; # Plant
|
||||
$WHS = isset($ICM428M->R428WH) ? $ICM428M->R428WH : '322'; # WareHouse
|
||||
}
|
||||
$WHDDA = $COMPANY.$PLANT.$WHS;
|
||||
// dump($WHDDA);
|
||||
# Warehouse Table
|
||||
$IC670M = DB::connection(config('m3.connection', 'pgsql'))->table('ic670m')->get();
|
||||
}
|
||||
catch (\Throwable $th) {
|
||||
Log::error($th);
|
||||
}
|
||||
|
||||
return view('m3::liberty-theme.pages.execSummary',compact('IC670M','WHDDA'));
|
||||
// ,'ICM688M2',,'COMPANY','PLANT','WHS','reportDate'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use DB;
|
||||
use Config;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Str;
|
||||
use Log;
|
||||
|
||||
|
||||
class execSummaryLineController extends Controller
|
||||
{
|
||||
public static function index(Request $request){
|
||||
try {
|
||||
# Ajax Call
|
||||
if ($request->ajax()) {
|
||||
// dump($request->all());
|
||||
$WHDDA = isset($request->WHDDA) ? $request->WHDDA : array();
|
||||
$WHArr = array();
|
||||
foreach ($WHDDA as $key => $WHDDAV) {
|
||||
$CO = substr($WHDDAV, 0, 3);
|
||||
// $R428PL = substr($WHDDAV, 3, 3);
|
||||
$WHArr[] = substr($WHDDAV, 6, 3);
|
||||
}
|
||||
|
||||
$reportPeriod = isset($request->reportPeriod) ? $request->reportPeriod : ''; # monthly , quarter , year , daily
|
||||
# Current
|
||||
$checkSales = isset($request->checkSales) ? $request->checkSales : ''; # on
|
||||
$checkWeight = isset($request->checkWeight) ? $request->checkWeight : ''; # on
|
||||
$checkLines = isset($request->checkLines) ? $request->checkLines : ''; # on
|
||||
|
||||
if(count($WHArr)>0 && $CO!='' && $reportPeriod!=''){
|
||||
switch ($reportPeriod) {
|
||||
case 'year':
|
||||
# Set Dates based on reportPeriod type
|
||||
$firstDay = isset($request->REPORTDATE) ? \DateTime::createFromFormat('Y-m', $request->REPORTDATE) : '';
|
||||
$reportDate = $firstDay->modify('first day of January')->format('Ymd');
|
||||
|
||||
$lastDay = isset($request->TOREPORTDATE) ? \DateTime::createFromFormat('Y-m', trim($request->TOREPORTDATE)) : '';
|
||||
$toreportDate = $lastDay->modify('last day of December')->format('Ymd');
|
||||
|
||||
# Build SQL
|
||||
$selectContent = "with tempfile as (
|
||||
select a5rsvqty,a5packed,a5slunpr*a5packed as dollars,a5lnwght,a5whs,
|
||||
(select max(ayapr8N002) as ayapr8N002 from icm695m1 where a5macpkr=aymacpkr fetch first 1 rows only)
|
||||
from icm688m2 where a5macpkr in (
|
||||
select distinct aymacpkr from icm695m1 where (AYSTATUS in ('Z','z') and ayapr8N002>=$reportDate and ayapr8N002<=$toreportDate )
|
||||
) and a5co='".$CO."' and a5whs in(".implode(",", $WHArr).")
|
||||
)
|
||||
select substr(ayapr8N002,1,4) as years,count(*) as lines,sum(a5rsvqty) as reserveqty,sum(a5packed) as packed,sum(a5lnwght*a5packed/a5rsvqty) as weight,sum(dollars) as dollars,a5whs as whs from tempfile
|
||||
group by substr(ayapr8N002,1,4),a5whs order by 1 ";
|
||||
|
||||
$execSummaryResLY = [];
|
||||
break;
|
||||
|
||||
case 'quarter':
|
||||
# Set Dates based on reportPeriod type
|
||||
$firstDay = isset($request->REPORTDATE) ? \DateTime::createFromFormat('Y-m', $request->REPORTDATE) : '';
|
||||
$reportDate = $firstDay->modify('first day of January')->format('Ymd');
|
||||
|
||||
$lastDay = isset($request->TOREPORTDATE) ? \DateTime::createFromFormat('Y-m', trim($request->TOREPORTDATE)) : '';
|
||||
$toreportDate = $lastDay->modify('last day of December')->format('Ymd');
|
||||
# Build SQL
|
||||
$selectContent = "with tempfile as (
|
||||
select a5rsvqty,a5packed,a5slunpr*a5packed as dollars,a5lnwght,a5whs,
|
||||
(select max(ayapr8N002) as ayapr8N002 from icm695m1 where a5macpkr=aymacpkr fetch first 1 rows only)
|
||||
from icm688m2 where a5macpkr in (
|
||||
select distinct aymacpkr from icm695m1 where (AYSTATUS in ('Z','z') and ayapr8N002>=$reportDate and ayapr8N002<=$toreportDate )
|
||||
) and a5co='".$CO."' and a5whs in (".implode(",", $WHArr).")
|
||||
)
|
||||
select 'Q' || EXTRACT(QUARTER FROM TO_DATE(CAST(ayapr8n002 AS TEXT),'YYYYMMDD')) ||'-' || substr(ayapr8N002,3,2) as years,count(*) as lines,
|
||||
sum(a5rsvqty) as reserveqty, sum(a5packed) as packed,sum (a5lnwght*a5packed/a5rsvqty) as weight,sum(dollars) as dollars, a5whs as whs
|
||||
from tempfile
|
||||
group by 'Q' || EXTRACT(QUARTER FROM TO_DATE(CAST(ayapr8n002 AS TEXT),'YYYYMMDD')) ||'-' || substr(ayapr8N002,3,2),a5whs order by 1 ";
|
||||
|
||||
$execSummaryResLY = [];
|
||||
|
||||
break;
|
||||
|
||||
case 'monthly':
|
||||
# Set Dates based on reportPeriod type
|
||||
$firstDay = isset($request->REPORTDATE) ? \DateTime::createFromFormat('Y-m', $request->REPORTDATE) : null;
|
||||
|
||||
$lastDay = (clone $firstDay);
|
||||
$reportDate = $firstDay->modify('-11 months')->modify('first day of this month')->format('Ymd'); //
|
||||
$toreportDate = $lastDay ? $lastDay->modify('last day of this month')->format('Ymd') : '';
|
||||
# Last Year Dates
|
||||
// Same period, but for Last Year (LY)
|
||||
$reportDateLY = (clone $firstDay)->modify('-1 year')->modify('first day of this month')->format('Ymd');
|
||||
$toreportDateLY = (clone $lastDay)->modify('-1 year')->modify('last day of this month')->format('Ymd');
|
||||
|
||||
# Build SQL
|
||||
$selectContent = "with tempfile as (
|
||||
select a5rsvqty,a5packed,a5slunpr*a5packed as dollars,a5lnwght,a5whs,
|
||||
(select max(ayapr8N002) as ayapr8N002 from icm695m1 where a5macpkr=aymacpkr fetch first 1 rows only)
|
||||
from icm688m2 where a5macpkr in (
|
||||
select distinct aymacpkr from icm695m1 where (AYSTATUS in ('Z','z') and ayapr8N002>=$reportDate and ayapr8N002<=$toreportDate )
|
||||
) and a5co='".$CO."' and a5whs in (".implode(",", $WHArr).")
|
||||
)
|
||||
select substr(ayapr8N002,1,4) || '-' || substr(ayapr8N002,5,2) as years,count(*) as lines,sum(a5rsvqty) as reserveqty,sum(a5packed) as packed,
|
||||
sum(a5lnwght*a5packed/a5rsvqty) as weight,sum(dollars) as dollars, a5whs as whs
|
||||
from tempfile
|
||||
group by substr(ayapr8N002,1,4) || '-' || substr(ayapr8N002,5,2),a5whs order by 1 ";
|
||||
|
||||
$selectContentLY = "with tempfile as (
|
||||
select a5rsvqty,a5packed,a5slunpr*a5packed as dollars,a5lnwght,a5whs,
|
||||
(select max(ayapr8N002) as ayapr8N002 from icm695m1 where a5macpkr=aymacpkr fetch first 1 rows only)
|
||||
from icm688m2 where a5macpkr in (
|
||||
select distinct aymacpkr from icm695m1 where (AYSTATUS in ('Z','z') and ayapr8N002>=$reportDateLY and ayapr8N002<=$toreportDateLY )
|
||||
) and a5co='".$CO."' and a5whs in (".implode(",", $WHArr).")
|
||||
)
|
||||
select substr(ayapr8N002,1,4) || '-' || substr(ayapr8N002,5,2) as years,count(*) as lines,sum(a5rsvqty) as reserveqty,sum(a5packed) as packed,
|
||||
sum(a5lnwght*a5packed/a5rsvqty) as weight,sum(dollars) as dollars, a5whs as whs
|
||||
from tempfile
|
||||
group by substr(ayapr8N002,1,4) || '-' || substr(ayapr8N002,5,2),a5whs order by 1 ";
|
||||
|
||||
$execSummaryResLY = DB::connection(config('m3.connection', 'pgsql'))->select($selectContentLY);
|
||||
|
||||
break;
|
||||
|
||||
case 'custom':
|
||||
# Set Dates based on reportPeriod type
|
||||
$firstDay = isset($request->REPORTDATE) ? \DateTime::createFromFormat('Y-m', $request->REPORTDATE) : '';
|
||||
$reportDate = $firstDay->modify('first day of this month')->format('Ymd');
|
||||
$toreportDate = $firstDay->modify('last day of this month')->format('Ymd');
|
||||
|
||||
# Last Year Dates
|
||||
$reportDateLY = (clone $firstDay)->modify('-1 year')->modify('first day of this month')->format('Ymd');
|
||||
$toreportDateLY = (clone $firstDay)->modify('-1 year')->modify('last day of this month')->format('Ymd');
|
||||
|
||||
# Build SQL
|
||||
$selectContent = "with tempfile as (
|
||||
select a5rsvqty,a5packed,a5slunpr*a5packed as dollars,a5lnwght,a5whs,
|
||||
(select max(ayapr8N002) as ayapr8N002 from icm695m1 where a5macpkr=aymacpkr fetch first 1 rows only)
|
||||
from icm688m2 where a5macpkr in (
|
||||
select distinct aymacpkr from icm695m1 where (AYSTATUS in ('Z','z') and ayapr8N002>=$reportDate and ayapr8N002<=$toreportDate )
|
||||
) and a5co='".$CO."' and a5whs in (".implode(",", $WHArr).")
|
||||
)
|
||||
select substr(ayapr8N002,7,2) as years,count(*) as lines,sum(a5rsvqty) as reserveqty,sum(a5packed) as packed,
|
||||
sum(a5lnwght*a5packed/a5rsvqty) as weight, sum(dollars) as dollars, a5whs as whs
|
||||
from tempfile
|
||||
group by substr(ayapr8N002,7,2),a5whs order by 1 ";
|
||||
|
||||
$selectContentLY = "with tempfile as (
|
||||
select a5rsvqty,a5packed,a5slunpr*a5packed as dollars,a5lnwght,a5whs,
|
||||
(select max(ayapr8N002) as ayapr8N002 from icm695m1 where a5macpkr=aymacpkr fetch first 1 rows only)
|
||||
from icm688m2 where a5macpkr in (
|
||||
select distinct aymacpkr from icm695m1 where (AYSTATUS in ('Z','z') and ayapr8N002>=$reportDateLY and ayapr8N002<=$toreportDateLY )
|
||||
) and a5co='".$CO."' and a5whs in (".implode(",", $WHArr).")
|
||||
)
|
||||
select substr(ayapr8N002,7,2) as years,count(*) as lines,sum(a5rsvqty) as reserveqty,sum(a5packed) as packed,
|
||||
sum(a5lnwght*a5packed/a5rsvqty) as weight, sum(dollars) as dollars, a5whs as whs
|
||||
from tempfile
|
||||
group by substr(ayapr8N002,7,2),a5whs order by 1 ";
|
||||
|
||||
$execSummaryResLY = DB::connection(config('m3.connection', 'pgsql'))->select($selectContentLY);
|
||||
break;
|
||||
|
||||
default:
|
||||
$selectContent = "";
|
||||
break;
|
||||
}
|
||||
|
||||
$execSummaryRes = DB::connection(config('m3.connection', 'pgsql'))->select($selectContent);
|
||||
}
|
||||
else{
|
||||
$execSummaryRes = collect();
|
||||
$execSummaryResLY = collect();
|
||||
}
|
||||
|
||||
return response()->json(['success'=>true,'reportPeriod'=> $reportPeriod, 'result'=>$execSummaryRes, 'resultLY'=>$execSummaryResLY,
|
||||
'checkSales'=>$checkSales, 'checkWeight'=>$checkWeight, 'checkLines'=>$checkLines]);
|
||||
}
|
||||
|
||||
# Init Page
|
||||
$SHUSER = m3_user() !== '' ? Str::upper(trim(m3_user())) : '';
|
||||
// dd($SHUSER);
|
||||
if ($SHUSER!='') {
|
||||
# Get User CO & WH from Table ICM428M
|
||||
$ICM428M = DB::connection(config('m3.connection', 'pgsql'))->table('icm428m')
|
||||
->select('R428US','R428CO', 'R428WH','R428PL')
|
||||
->where('R428US','=',$SHUSER)
|
||||
->first();
|
||||
|
||||
$R428US = isset($ICM428M->R428US) ? $ICM428M->R428US : ''; # User
|
||||
$COMPANY = isset($ICM428M->R428CO) ? $ICM428M->R428CO : '110'; # Company
|
||||
$PLANT = isset($ICM428M->R428PL) ? $ICM428M->R428PL : '144'; # Plant
|
||||
$WHS = isset($ICM428M->R428WH) ? $ICM428M->R428WH : '322'; # WareHouse
|
||||
}
|
||||
$WHDDA = $COMPANY.$PLANT.$WHS;
|
||||
// dump($WHDDA);
|
||||
# Warehouse Table
|
||||
$IC670M = DB::connection(config('m3.connection', 'pgsql'))->table('ic670m')->get();
|
||||
}
|
||||
catch (\Throwable $th) {
|
||||
Log::error($th);
|
||||
}
|
||||
|
||||
return view('m3::liberty-theme.pages.execSummaryLine',compact('IC670M','WHDDA'));
|
||||
// ,'ICM688M2',,'COMPANY','PLANT','WHS','reportDate'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\M3\Http\Controllers;
|
||||
|
||||
use Modules\M3\Http\Controllers\Controller;
|
||||
use DB;
|
||||
use Config;
|
||||
use Storage;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Modules\M3\Services\BillOfLadingService;
|
||||
use setasign\Fpdi\Fpdi;
|
||||
|
||||
|
||||
class fillBOL2Controller extends Controller
|
||||
{
|
||||
protected $bolService;
|
||||
|
||||
public function __construct(BillOfLadingService $bolService)
|
||||
{
|
||||
$this->bolService = $bolService;
|
||||
}
|
||||
|
||||
public static function index(Request $request) {
|
||||
|
||||
return view('m3::liberty-theme.pages.fillBOL2');
|
||||
|
||||
}
|
||||
|
||||
public function fillBOL(Request $request)
|
||||
{
|
||||
|
||||
## $BOL = BOL::findOrFail($request);
|
||||
$BOL = $request;
|
||||
|
||||
$data = [
|
||||
'bol_number' => $request->input('BOL_number') ?? '1234567890',
|
||||
'shipper_no' => $request->input('shipper_no') ?? '1234567890',
|
||||
'date' => now()->format('m/d/Y') ?? '01/01/2000',
|
||||
'master_bill_no' => $request->input('master_bill_no') ? 'X' : 'X',
|
||||
'master_bill_yes' => $request->input('master_bill_yes') ? 'X' : '',
|
||||
'master_bill_drops' => $request->input('master_bill_drops') ?? '',
|
||||
'consignor_name' => $request->input('consignor_name') ?? 'ERICO INTERNATIONAL CORP',
|
||||
'consignor_address1' => $request->input('consignor_address1') ?? '6800 ARNOLD MILLER PARKWAY',
|
||||
'consignor_address2' => $request->input('consignor_address2') ?? 'SOLON, OH 44139',
|
||||
'consignor_address3' => $request->input('consignor_address3') ?? 'USA',
|
||||
'consignee_name' => $request->input('consignee_name') ?? 'ERICO EUROPE BV',
|
||||
'consignee_address1' => $request->input('consignee_address1') ?? 'JULES VERNEWEG 75',
|
||||
'consignee_address2' => $request->input('consignee_address2') ?? '',
|
||||
'consignee_address3' => $request->input('consignee_address3') ?? 'TILBURG . 5015 BG',
|
||||
'freight_collect' => $request->input('freight_collect') ? 'X' : 'X',
|
||||
'carrier_name' => $request->input('carrier_name') ?? 'ICL / Expeditors',
|
||||
|
||||
'pieces' => $request->input('pieces') ?? '20',
|
||||
'line_class' => $request->input('line_class') ?? '50',
|
||||
'line_weight' => $request->input('line_weight') ?? '8320',
|
||||
|
||||
'total_pieces' => $request->input('total_pieces') ?? '20',
|
||||
'total_line_weight' => $request->input('total_line_weight') ?? '8320',
|
||||
'description' => $request->input('description') ?? 'Package Description sfdfsdfasdfas dfasdfasdfcasdfvasfa clsdalcdfl
|
||||
Line 2
|
||||
Line 3
|
||||
Line 4
|
||||
Line 5',
|
||||
|
||||
'DTESHIPED.1' => date('d/m/Y'),
|
||||
'invoice_number' => $BOL['BOL_number'],
|
||||
'amount_due' => number_format($BOL['amount'], 2),
|
||||
'TYPEANDESCPTN.1' => 'TOTAL: 20 SKIDS 8320 #',
|
||||
'TYPEANDESCPTN.10' => 'ROTTERDAM ETA: 11/22',
|
||||
'TYPEANDESCPTN.13' => 'CONTAINER:',
|
||||
'TYPEANDESCPTN.2' => 'MECHANICAL / CADDY/ ELECTRICAL',
|
||||
'TYPEANDESCPTN.4' => 'BOOKING: 150744100',
|
||||
'TYPEANDESCPTN.5' => 'REFERENCE: 3140028046',
|
||||
'TYPEANDESCPTN.6' => 'VESSEL: INDEPENDENT HORIZON V. 1023E',
|
||||
'TYPEANDESCPTN.7' => 'SEAL: 637053',
|
||||
'TYPEANDESCPTN.9' => 'CHESTER, PA ETD: 11/05',
|
||||
'BOFLADNGAGYCD' => $BOL['BOL_number'],
|
||||
'CLASSORATE1' => '50',
|
||||
'CNMETRKLICNSE' => 'ICL / Expeditors',
|
||||
'CONSIGTONMADDR' => 'ERICO EUROPE BV JULES VERNEWEG 75 TILBURG . 5015 BG',
|
||||
'DATE' => date('d/m/Y'),
|
||||
'FRMNMADDR' => 'ERICO INTERNATIONAL CORP 6800 ARNOLD MILLER PARKWAY SOLON, OH 44139 USA',
|
||||
'LNITEMWT1' => '8320',
|
||||
'PARTOFMSTRBILL' => 'No',
|
||||
'PKGTYPECOUNT1' => '20',
|
||||
'SHPRNMBR' => '3140028046',
|
||||
'TOTALWT' => '8320',
|
||||
'TOTPIECES' => '20',
|
||||
'ckFREIGHTCOLECT' => 'Yes',
|
||||
'ckPREPAY' => 'Off',
|
||||
|
||||
'DTESHIPED.2' => '',
|
||||
'LNITEMWT24' => '',
|
||||
'CLASSORATE24' => '',
|
||||
'LNITEMCLAS24' => '',
|
||||
'TYPEANDESCPTN.24' => '',
|
||||
'PKGTYPECOUNT24' => '',
|
||||
'LNITEMWT23' => '',
|
||||
'CLASSORATE23' => '',
|
||||
'LNITEMCLAS23' => '',
|
||||
'TYPEANDESCPTN.23' => '',
|
||||
'PKGTYPECOUNT23' => '',
|
||||
'LNITEMWT22' => '',
|
||||
'CLASSORATE22' => '',
|
||||
'LNITEMCLAS22' => '',
|
||||
'TYPEANDESCPTN.22' => '',
|
||||
'PKGTYPECOUNT22' => '',
|
||||
'LNITEMWT21' => '',
|
||||
'CLASSORATE21' => '',
|
||||
'LNITEMCLAS21' => '',
|
||||
'TYPEANDESCPTN.21' => '',
|
||||
'PKGTYPECOUNT21' => '',
|
||||
'LNITEMWT20' => '',
|
||||
'CLASSORATE20' => '',
|
||||
'LNITEMCLAS20' => '',
|
||||
'TYPEANDESCPTN.20' => '',
|
||||
'PKGTYPECOUNT20' => '',
|
||||
'LNITEMWT19' => '',
|
||||
'CLASSORATE19' => '',
|
||||
'LNITEMCLAS19' => '',
|
||||
'TYPEANDESCPTN.19' => '',
|
||||
'PKGTYPECOUNT19' => '',
|
||||
'LNITEMWT18' => '',
|
||||
'CLASSORATE18' => '',
|
||||
'LNITEMCLAS18' => '',
|
||||
'TYPEANDESCPTN.18' => '',
|
||||
'PKGTYPECOUNT18' => '',
|
||||
'LNITEMWT17' => '',
|
||||
'CLASSORATE17' => '',
|
||||
'LNITEMCLAS17' => '',
|
||||
'TYPEANDESCPTN.17' => '',
|
||||
'PKGTYPECOUNT17' => '',
|
||||
'LNITEMWT16' => '',
|
||||
'CLASSORATE16' => '',
|
||||
'LNITEMCLAS16' => '',
|
||||
'TYPEANDESCPTN.16' => '',
|
||||
'PKGTYPECOUNT16' => '',
|
||||
'LNITEMWT15' => '',
|
||||
'CLASSORATE15' => '',
|
||||
'LNITEMCLAS15' => '',
|
||||
'TYPEANDESCPTN.15' => '',
|
||||
'PKGTYPECOUNT15' => '',
|
||||
'LNITEMWT14' => '',
|
||||
'CLASSORAT14' => '',
|
||||
'LNITEMCLAS14' => '',
|
||||
'TYPEANDESCPTN.14' => '',
|
||||
'PKGTYPECOUNT14' => '',
|
||||
'LNITEMWT13' => '',
|
||||
'CLASSORATE13' => '',
|
||||
'LNITEMCLAS13' => '',
|
||||
'PKGTYPECOUNT13' => '',
|
||||
'LNITEMWT12' => '',
|
||||
'CLASSORATE12' => '',
|
||||
'LNITEMCLAS12' => '',
|
||||
'TYPEANDESCPTN.12' => '',
|
||||
'PKGTYPECOUNT12' => '',
|
||||
'LNITEMWT11' => '',
|
||||
'CLASSORATE11' => '',
|
||||
'LNITEMCLAS11' => '',
|
||||
'TYPEANDESCPTN.11' => '',
|
||||
'PKGTYPECOUNT11' => '',
|
||||
'LNITEMWT10' => '',
|
||||
'CLASSORATE10' => '',
|
||||
'LNITEMCLAS10' => '',
|
||||
'PKGTYPECOUNT10' => '',
|
||||
'LNITEMWT9' => '',
|
||||
'CLASSORATE9' => '',
|
||||
'LNITEMCLAS8' => '',
|
||||
'PKGTYPECOUNT9' => '',
|
||||
'LNITEMWT8' => '',
|
||||
'CLASSORATE8' => '',
|
||||
'TYPEANDESCPTN.8' => '',
|
||||
'PKGTYPECOUNT8' => '',
|
||||
'LNITEMWT7' => '',
|
||||
'CLASSORATE7' => '',
|
||||
'LNITEMCLAS7' => '',
|
||||
'PKGTYPECOUNT7' => '',
|
||||
'LNITEMWT6' => '',
|
||||
'CLASSORATE6' => '',
|
||||
'LNITEMCLAS6' => '',
|
||||
'PKGTYPECOUNT6' => '',
|
||||
'LNITEMWT5' => '',
|
||||
'CLASSORATE5' => '',
|
||||
'LNITEMCLAS5' => '',
|
||||
'PKGTYPECOUNT5' => '',
|
||||
'LNITEMWT4' => '',
|
||||
'CLASSORATE4' => '',
|
||||
'LNITEMCLAS4' => '',
|
||||
'PKGTYPECOUNT4' => '',
|
||||
'LNITEMWT3' => '',
|
||||
'CLASSORATE3' => '',
|
||||
'LNITEMCLAS3' => '',
|
||||
'TYPEANDESCPTN.3' => '',
|
||||
'PKGTYPECOUNT3' => '',
|
||||
'LNITEMWT2' => '',
|
||||
'CLASSORATE2' => '',
|
||||
'LNITEMCLAS2' => '',
|
||||
'PKGTYPECOUNT2' => '',
|
||||
'LNITEMCLAS1' => '',
|
||||
'HAZLNITEMWT3' => '',
|
||||
'HAZCLASSORATE3' => '',
|
||||
'HAZLNITEMCLAS3' => '',
|
||||
'HAZMATERDESL3' => '',
|
||||
'HAZMATERL3' => '',
|
||||
'HAZLNITEMWT2' => '',
|
||||
'HAZCLASSORATE2' => '',
|
||||
'HAZLNITEMCLAS2' => '',
|
||||
'HAZMATERDESL2' => '',
|
||||
'HAZMATERL2' => '',
|
||||
'HAZLNITEMWT1' => '',
|
||||
'HAZCLASSORATE1' => '',
|
||||
'HAZLNITEMCLAS1' => '',
|
||||
'HAZMATERDESL1' => '',
|
||||
'HAZMATERL1' => '',
|
||||
'24HREMGCYRSPNS' => '',
|
||||
'CARIERFEDEMPID' => '',
|
||||
'BILLTOADDR' => '',
|
||||
'NUMDROPS' => '',
|
||||
|
||||
];
|
||||
|
||||
try {
|
||||
$filledPdf = $this->bolService->fillBillOfLading($data);
|
||||
|
||||
return response()->download($filledPdf)->deleteFileAfterSend(true);
|
||||
} catch (\Exception $e) {
|
||||
return response()->json(['error' => $e->getMessage()], 500);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user