Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sarun Mungthanya
SpnPatch-Laravel
Commits
a4b0f3d1
Commit
a4b0f3d1
authored
Nov 12, 2024
by
Chanon.u
Browse files
Add manual response feature
parent
7885f031
Changes
24
Show whitespace changes
Inline
Side-by-side
app/Http/Controllers/ManualResponse/GenXmlController.php
0 → 100644
View file @
a4b0f3d1
<?php
namespace
App\Http\Controllers\ManualResponse
;
use
App\Http\Controllers\Controller
;
use
App\Models\ManualResponse\MasterResponseTemplates
;
use
App\Models\ManualResponse\DeclarationRunning
;
use
Illuminate\Support\Facades\DB
;
use
SimpleXMLElement
;
use
DOMDocument
;
use
Carbon\Carbon
;
class
GenXmlController
extends
Controller
{
public
function
generateXML
(
$templateId
,
$documentType
,
$lockData
)
{
$template
=
MasterResponseTemplates
::
join
(
'mr_master_messages as mm'
,
'mr_master_response_templates.mid'
,
'='
,
'mm.id'
)
->
select
(
'mm.name as messageName'
,
'mr_master_response_templates.id as templateId'
,
'mr_master_response_templates.template'
)
->
where
(
'mr_master_response_templates.id'
,
$templateId
)
->
first
();
if
(
empty
(
$template
))
{
return
null
;
}
$json
=
json_decode
(
$template
[
'template'
],
true
);
if
(
$json
!=
null
){
return
$this
->
genXmlFromTemplate
(
$json
,
$documentType
,
$lockData
);
}
}
private
function
genXmlFromTemplate
(
$json
,
$documentType
=
'0'
,
$lockData
=
true
,
$xml
=
null
,
&
$xmlData
=
[])
{
if
(
$xml
===
null
)
{
$rootElement
=
$json
[
'root'
];
$namespace
=
$json
[
'namespace'
];
unset
(
$json
[
'root'
],
$json
[
'namespace'
]);
if
(
$namespace
!==
''
){
$xml
=
new
SimpleXMLElement
(
"<?xml version=
\"
1.0
\"
encoding=
\"
UTF-8
\"
?><
$rootElement
xmlns=
\"
$namespace
\"
></
$rootElement
>"
);
}
else
{
$xml
=
new
SimpleXMLElement
(
"<?xml version=
\"
1.0
\"
encoding=
\"
UTF-8
\"
?><
$rootElement
></
$rootElement
>"
);
}
}
foreach
(
$json
as
$key
=>
$value
)
{
if
(
is_array
(
$value
))
{
if
(
is_numeric
(
$key
))
{
$key
=
'item'
.
$key
;
// dealing with <0/>..<n/> issues
}
$new_object
=
$xml
->
addChild
(
$key
);
$this
->
genXmlFromTemplate
(
$value
,
$documentType
,
$lockData
,
$new_object
,
$xmlData
);
// Pass by reference
}
else
{
if
(
is_numeric
(
$key
))
{
$key
=
'item'
.
$key
;
// dealing with <0/>..<n/> issues
}
if
(
empty
(
$value
))
{
if
(
!
$lockData
&&
in_array
(
$key
,
[
'DeclarationNumber'
,
'DocumentNumber'
])
&&
$documentType
!==
null
){
$value
=
$this
->
generateDeclarationNo
(
$documentType
);
}
else
if
(
!
$lockData
&&
$key
==
'GoodsTransitionNumber'
){
$value
=
$this
->
generateGCLNo
();
}
if
(
in_array
(
$key
,
[
'AuditDateTime'
])){
$value
=
Carbon
::
now
()
->
setTimezone
(
'GMT+7'
)
->
format
(
'Y-m-d\TH:i:s'
);
}
$child
=
$xml
->
addChild
(
$key
);
$child
[
0
]
=
''
;
// Ensure closed tag for empty value
}
else
{
$xml
->
addChild
(
$key
,
htmlspecialchars
(
$value
));
}
$xmlData
[
$key
]
=
$value
;
// Collect all tags as editable
}
}
$xmlNoData
=
[];
foreach
(
$xmlData
as
$key
=>
$val
){
$xmlNoData
[
$key
]
=
''
;
}
//$this->updateXmlValues($this->formatXml($xml->asXML()), $xmlNoData)
return
[
'xmlContent'
=>
$this
->
formatXml
(
$xml
->
asXML
()),
'xmlWithData'
=>
$xmlData
,
'xmlNoData'
=>
$xmlNoData
];
}
//Convert short tag in case of value is empty to closed tag
private
function
formatXml
(
$xmlString
)
{
$dom
=
new
DOMDocument
(
'1.0'
,
'UTF-8'
);
$dom
->
preserveWhiteSpace
=
false
;
$dom
->
formatOutput
=
true
;
$dom
->
loadXML
(
$xmlString
);
// Ensure empty tags are closed
$xpath
=
new
\
DOMXPath
(
$dom
);
foreach
(
$xpath
->
query
(
'//*[not(*) and not(text())]'
)
as
$node
)
{
$node
->
nodeValue
=
''
;
// Set node value to empty string to ensure closed tag
}
return
$dom
->
saveXML
();
}
public
function
updateXmlValues
(
$xmlString
,
$tagsToUpdate
)
{
$dom
=
new
DOMDocument
(
'1.0'
,
'UTF-8'
);
$dom
->
loadXML
(
$xmlString
);
foreach
(
$tagsToUpdate
as
$tag
=>
$value
)
{
$nodes
=
$dom
->
getElementsByTagName
(
$tag
);
foreach
(
$nodes
as
$node
)
{
$node
->
nodeValue
=
htmlspecialchars
(
$value
);
}
}
return
$dom
->
saveXML
();
}
private
function
generateDeclarationNo
(
$documentType
)
{
$currentDate
=
Carbon
::
now
()
->
toDateString
();
$maxRunningNumber
=
999999
;
$running
=
DB
::
transaction
(
function
()
use
(
$currentDate
,
$maxRunningNumber
,
$documentType
)
{
$runningNumberRecord
=
DeclarationRunning
::
lockForUpdate
()
->
where
(
'document_type'
,
$documentType
)
->
first
();
if
(
$runningNumberRecord
)
{
if
(
$runningNumberRecord
->
last_updated_date
!==
$currentDate
)
{
// Reset the running number if the date has changed
$runningNumberRecord
->
running_number
=
1
;
$runningNumberRecord
->
last_updated_date
=
$currentDate
;
}
elseif
(
$runningNumberRecord
->
running_number
>=
$maxRunningNumber
)
{
// Reset the running number if it reaches the max value
$runningNumberRecord
->
running_number
=
1
;
}
else
{
// Increment the running number
$runningNumberRecord
->
running_number
+=
1
;
}
$runningNumberRecord
->
save
();
}
else
{
// Create a new record if none exists
$runningNumberRecord
=
DeclarationRunning
::
create
([
'running_number'
=>
1
,
'last_updated_date'
=>
$currentDate
,
'document_type'
=>
$documentType
,
]);
}
return
str_pad
(
$runningNumberRecord
->
running_number
,
6
,
'0'
,
STR_PAD_LEFT
);
});
$tmp_declarationNo
=
[
"A"
,
substr
(
$running
,
0
,
1
),
Carbon
::
now
()
->
format
(
'd'
),
$documentType
,
substr
(
Carbon
::
now
()
->
year
+
543
,
-
2
),
Carbon
::
now
()
->
format
(
'm'
),
substr
(
$running
,
-
5
)
];
return
implode
(
''
,
$tmp_declarationNo
);
}
function
generateGCLNo
(){
$currentDate
=
Carbon
::
now
()
->
toDateString
();
$maxRunningNumber
=
9999999
;
$running
=
DB
::
transaction
(
function
()
use
(
$currentDate
,
$maxRunningNumber
)
{
$runningNumberRecord
=
DeclarationRunning
::
lockForUpdate
()
->
where
(
'document_type'
,
"GCL"
)
->
first
();
if
(
$runningNumberRecord
)
{
if
(
$runningNumberRecord
->
last_updated_date
!==
$currentDate
)
{
// Reset the running number if the date has changed
$runningNumberRecord
->
running_number
=
1
;
$runningNumberRecord
->
last_updated_date
=
$currentDate
;
}
elseif
(
$runningNumberRecord
->
running_number
>=
$maxRunningNumber
)
{
// Reset the running number if it reaches the max value
$runningNumberRecord
->
running_number
=
1
;
}
else
{
// Increment the running number
$runningNumberRecord
->
running_number
+=
1
;
}
$runningNumberRecord
->
save
();
}
else
{
// Create a new record if none exists
$runningNumberRecord
=
DeclarationRunning
::
create
([
'running_number'
=>
1
,
'last_updated_date'
=>
$currentDate
,
'document_type'
=>
"GCL"
,
]);
}
return
str_pad
(
$runningNumberRecord
->
running_number
,
7
,
'0'
,
STR_PAD_LEFT
);
});
$tmp_GCLNo
=
[
substr
(
Carbon
::
now
()
->
year
+
543
,
-
2
),
Carbon
::
now
()
->
format
(
'm'
),
"A"
,
$running
];
return
implode
(
''
,
$tmp_GCLNo
);
}
}
app/Http/Controllers/ManualResponse/ManualResponseController.php
0 → 100644
View file @
a4b0f3d1
<?php
namespace
App\Http\Controllers\ManualResponse
;
use
Illuminate\Http\Request
;
use
App\Http\Controllers\Controller
;
class
ManualResponseController
extends
Controller
{
public
function
index
()
{
//return view('manual-response/index');
$currentContent
=
'ManualResponse'
;
return
view
(
'.home'
,
compact
(
'currentContent'
));
}
}
app/Http/Controllers/ManualResponse/SpnConfigController.php
0 → 100644
View file @
a4b0f3d1
<?php
namespace
App\Http\Controllers\ManualResponse
;
use
App\Models\ManualResponse\UsersConnectSpn
;
use
App\Http\Controllers\Controller
;
class
SpnConfigController
extends
Controller
{
public
function
init_connection
(
UsersConnectSpn
$user
)
{
$username
=
$user
->
username
;
$password
=
$user
->
password
;
$link
=
$user
->
link
;
// Initialize cURL
$ch
=
curl_init
();
curl_setopt
(
$ch
,
CURLOPT_URL
,
"
$link
/spn/login_api.php"
);
curl_setopt
(
$ch
,
CURLOPT_POST
,
1
);
curl_setopt
(
$ch
,
CURLOPT_RETURNTRANSFER
,
true
);
// Set the Authorization header for Basic Auth
curl_setopt
(
$ch
,
CURLOPT_HTTPHEADER
,
[
'Authorization: Basic '
.
base64_encode
(
"
$username
:
$password
"
),
]);
// Execute cURL request
$response
=
curl_exec
(
$ch
);
$error
=
curl_error
(
$ch
);
// Check for errors
$httpCode
=
curl_getinfo
(
$ch
,
CURLINFO_HTTP_CODE
);
//dd($response, $error, $httpCode); //Debug response of cURL
curl_close
(
$ch
);
// Close the cURL handle
if
(
$httpCode
==
'404'
){
return
[
'success'
=>
'false'
,
'message'
=>
'This endpoint does not support this feature. Please contact support for upgrade options.'
];
}
if
(
$error
)
{
return
[
'success'
=>
'false'
,
'message'
=>
'cURL Error: '
.
$error
];
}
// Process the response
$decodedResponse
=
json_decode
(
$response
,
true
);
if
(
json_last_error
()
!==
JSON_ERROR_NONE
)
{
session
()
->
flash
(
'error'
,
'Invalid JSON response'
);
return
null
;
// Handle invalid JSON appropriately
}
return
$decodedResponse
;
// Return the decoded response
}
}
app/Http/Livewire/Pages/ManualResponse/ManualResponse.php
0 → 100644
View file @
a4b0f3d1
<?php
namespace
App\Http\Livewire\Pages\ManualResponse
;
use
Illuminate\Support\Facades\Storage
;
use
Illuminate\Support\Facades\Auth
;
use
Livewire\Component
;
use
App\Http\Controllers\ManualResponse\GenXmlController
;
use
App\Http\Controllers\ManualResponse\SpnConfigController
;
use
App\Models\ManualResponse\MasterMessages
;
use
App\Models\ManualResponse\MasterResponseTemplates
;
use
App\Models\ManualResponse\MasterDocTypes
;
use
App\Models\ManualResponse\TabManualResponseLog
;
use
App\Models\ManualResponse\UsersConnectSpn
;
use
Carbon\Carbon
;
use
CURLFile
;
class
ManualResponse
extends
Component
{
public
$displayCustomizeDiv
=
false
;
public
$messageTypes
=
[];
public
$messageId
;
public
$responseTemplates
=
[];
public
$templateId
;
public
$templateList
;
public
$docTypes
=
[];
public
$docType
;
public
$xmlContent
;
public
$xmlData
=
[];
public
$xmlWithData
=
[];
public
$activeLoader
=
false
;
public
$changeBtnColor
;
public
$lockData
;
public
$disableLockData
=
true
;
public
$structureXML
;
protected
$rules
=
[
'messageId'
=>
'required|string'
,
'templateId'
=>
'required|string'
];
protected
$messages
=
[
'messageId.required'
=>
'*Message cannot be empty.'
,
'templateId.required'
=>
'*Template cannot be empty.'
];
public
function
mount
()
{
$this
->
messageTypes
=
MasterMessages
::
pluck
(
'value'
,
'id'
)
->
toArray
();
$this
->
docTypes
=
MasterDocTypes
::
pluck
(
'name'
,
'code'
)
->
toArray
();
$this
->
changeBtnColor
=
"bg-[#A020F0] hover:bg-[#B34FEF] text-white font-bold"
;
$this
->
lockData
=
false
;
$this
->
disableLockData
=
true
;
}
public
function
render
()
{
if
(
$this
->
messageId
!=
''
)
{
$this
->
responseTemplates
=
MasterResponseTemplates
::
where
(
'mid'
,
$this
->
messageId
)
->
get
()
->
mapWithKeys
(
function
(
$record
)
{
$description
=
$record
->
description
!=
''
?
' '
.
' ('
.
$record
->
description
.
')'
:
''
;
return
[
$record
->
id
=>
$record
->
code
.
': '
.
$record
->
name
.
$description
];
})
->
toArray
();
$this
->
docTypes
=
MasterDocTypes
::
where
(
'mid'
,
$this
->
messageId
)
->
pluck
(
'name'
,
'code'
)
->
toArray
();
}
return
view
(
'livewire.pages.manual-response.manual-response-index'
);
}
public
function
updatedMessageId
()
{
$this
->
templateId
=
''
;
$this
->
responseTemplates
=
[];
$this
->
docTypes
=
[];
$this
->
xmlData
=
[];
$this
->
xmlContent
=
''
;
$this
->
displayCustomizeDiv
=
false
;
}
public
function
updatedXmlTagInputList
()
{
if
(
$this
->
xmlData
===
null
)
{
$this
->
xmlContent
=
''
;
}
}
public
function
gotoCustomize
()
{
$this
->
disableLockData
=
false
;
$tmp_xmlData
=
$this
->
xmlData
;
$this
->
xmlData
=
[];
$this
->
xmlContent
=
''
;
$this
->
validate
();
//Default documentType in case messsage is export/import
if
(
empty
(
$this
->
docType
)){
if
(
$this
->
messageId
==
1
){
$this
->
docType
=
1
;
}
else
if
(
$this
->
messageId
==
2
){
$this
->
docType
=
0
;
}
}
$xmlGenerator
=
new
GenXmlController
();
$xml
=
$xmlGenerator
->
generateXML
(
$this
->
templateId
,
$this
->
docType
,
$this
->
lockData
);
if
(
$xml
==
null
)
{
session
()
->
flash
(
'templateNotFound'
,
'Template is not found!'
);
}
else
{
$this
->
displayCustomizeDiv
=
true
;
$this
->
xmlContent
=
$xml
[
'xmlContent'
];
$this
->
xmlData
=
$xml
[
'xmlWithData'
];
if
(
$this
->
lockData
){
foreach
(
$this
->
xmlData
as
$key
=>
$val
){
if
(
isset
(
$tmp_xmlData
[
$key
])
&&
$key
!=
'Message'
){
$this
->
xmlData
[
$key
]
=
$tmp_xmlData
[
$key
];
}
}
}
$this
->
reGenerateXML
();
}
$this
->
changeBtnColor
=
"bg-slate-150 font-medium text-slate-800 hover:bg-slate-200 focus:bg-slate-200 active:bg-slate-200/80 rounded-md border border-[#e5e7eb] "
;
}
public
function
reGenerateXML
()
{
$xmlGenerator
=
new
GenXmlController
();
$xml
=
$xmlGenerator
->
updateXmlValues
(
$this
->
xmlContent
,
$this
->
xmlData
);
$this
->
xmlContent
=
$xml
;
}
public
function
mockUpXML
()
{
$this
->
xmlData
=
$this
->
xmlWithData
;
}
public
function
generateAndUploadXml
()
{
$this
->
reGenerateXML
();
// Generate XML file from string
$now
=
Carbon
::
now
();
$filename
=
'manual_response_'
.
$now
->
format
(
'Ymd_His'
)
.
".xml"
;
Storage
::
disk
(
'local'
)
->
put
(
$filename
,
$this
->
xmlContent
);
$filePath
=
storage_path
(
'app/'
.
$filename
);
$currentUser
=
Auth
::
user
();
$userConnect
=
UsersConnectSpn
::
where
(
'uid'
,
$currentUser
->
id
)
->
first
();
if
(
!
isset
(
$userConnect
)){
$this
->
dispatchBrowserEvent
(
'open-modal'
,
[
'name'
=>
'alert-modal'
,
'message'
=>
'SPN config is not found!'
,
'status'
=>
'failed'
]);
return
;
}
$spnConfigController
=
new
SpnConfigController
();
$spnConfig
=
$spnConfigController
->
init_connection
(
$userConnect
);
if
(
$spnConfig
!=
null
&&
$spnConfig
[
'success'
]
==
'true'
){
$uid
=
$spnConfig
[
'uid'
];
$ucode
=
$spnConfig
[
'ucode'
];
$ch
=
curl_init
();
$cfile
=
new
CURLFile
(
$filePath
,
'application/xml'
,
$filename
);
$postData
=
[
'UID'
=>
$uid
,
'UCODE'
=>
$ucode
,
'SERVICENAME'
=>
'imcoreservice'
,
'ACTION'
=>
'get_response_customs'
,
'profilecode'
=>
''
,
'API_PLACE_FILE'
=>
'Y'
,
'file'
=>
$cfile
];
curl_setopt
(
$ch
,
CURLOPT_URL
,
$userConnect
->
link
.
"/IE5DEV.shippingnet/data_defaulttemplate.php"
);
curl_setopt
(
$ch
,
CURLOPT_POST
,
1
);
curl_setopt
(
$ch
,
CURLOPT_POSTFIELDS
,
$postData
);
curl_setopt
(
$ch
,
CURLOPT_RETURNTRANSFER
,
true
);
curl_exec
(
$ch
);
$error
=
curl_error
(
$ch
);
curl_close
(
$ch
);
TabManualResponseLog
::
create
([
'uid'
=>
$currentUser
->
id
,
'title'
=>
'Send Manual Response'
,
'detail'
=>
"Username: "
.
$userConnect
->
username
.
"
\n
Link: "
.
$userConnect
->
link
,
'xml_content'
=>
base64_encode
(
$this
->
xmlContent
),
'reference_number'
=>
$this
->
xmlData
[
'ReferenceNumber'
],
'declaration_number'
=>
$this
->
xmlData
[
'DeclarationNumber'
],
'link'
=>
$userConnect
->
link
]);
if
(
$error
)
{
//Cannot send response to SPN
$this
->
dispatchBrowserEvent
(
'open-modal'
,
[
'name'
=>
'alert-modal'
,
'message'
=>
'Cannot send response to SPN'
,
'status'
=>
'failed'
]);
}
else
{
$this
->
dispatchBrowserEvent
(
'open-modal'
,
[
'name'
=>
'alert-modal'
,
'message'
=>
'Send response successfully'
,
'status'
=>
'success'
]);
Storage
::
disk
(
'local'
)
->
delete
(
$filename
);
}
}
else
if
(
$spnConfig
!=
null
&&
$spnConfig
[
'success'
]
==
'false'
){
$this
->
dispatchBrowserEvent
(
'open-modal'
,
[
'name'
=>
'alert-modal'
,
'message'
=>
$spnConfig
[
'message'
],
'status'
=>
'failed'
]);
}
else
{
//Cannot get UID/UCODE from SPN
$this
->
dispatchBrowserEvent
(
'open-modal'
,
[
'name'
=>
'alert-modal'
,
'message'
=>
'Cannot connect to SPN'
,
'status'
=>
'failed'
]);
}
}
}
app/Http/Livewire/Pages/User/ConfigManualResponse.php
0 → 100644
View file @
a4b0f3d1
<?php
namespace
App\Http\Livewire\Pages\User
;
use
App\Models\User
;
use
App\Models\ManualResponse\UsersConnectSpn
;
use
App\Http\Controllers\ManualResponse\SpnConfigController
;
use
Livewire\Component
;
class
ConfigManualResponse
extends
Component
{
public
$editUserId
;
public
$editUsername
;
public
$usernameSPN
;
public
$passwordSPN
;
public
$linkSPN
;
public
$action
;
public
function
mount
(
$editUserId
)
{
$this
->
editUserId
=
$editUserId
;
$currentUser
=
User
::
find
(
$editUserId
);
$this
->
editUsername
=
$currentUser
->
first_name
;
$userConnectSpn
=
UsersConnectSpn
::
where
(
'uid'
,
$editUserId
)
->
first
();
if
(
$userConnectSpn
){
$this
->
usernameSPN
=
$userConnectSpn
->
username
;
$this
->
passwordSPN
=
""
;
$this
->
linkSPN
=
$userConnectSpn
->
link
;
}
}
public
function
updateConfig
()
{
if
(
empty
(
$this
->
usernameSPN
)){
$this
->
dispatchBrowserEvent
(
'open-modal'
,
[
'name'
=>
'alert-modal'
,
'message'
=>
'Username must not be empty!'
,
'status'
=>
'warning'
]);
return
;
}
$userConnectSpn
=
UsersConnectSpn
::
where
(
'uid'
,
$this
->
editUserId
)
->
first
();
if
(
$userConnectSpn
){
if
(
empty
(
$this
->
passwordSPN
)){
$this
->
dispatchBrowserEvent
(
'open-modal'
,
[
'name'
=>
'alert-modal'
,
'message'
=>
'Password must not be empty!'
,
'status'
=>
'warning'
]);
return
;
}
$userConnectSpn
->
username
=
$this
->
usernameSPN
;
$userConnectSpn
->
password
=
password_hash
(
$this
->
passwordSPN
,
PASSWORD_BCRYPT
);
$userConnectSpn
->
link
=
$this
->
linkSPN
;
$userConnectSpn
->
save
();
}
else
{
UsersConnectSpn
::
create
([
'uid'
=>
$this
->
editUserId
,
'username'
=>
$this
->
usernameSPN
,
'password'
=>
''
,
"link"
=>
$this
->
linkSPN
]);
}
$this
->
dispatchBrowserEvent
(
'open-modal'
,
[
'name'
=>
'alert-modal'
,
'message'
=>
'Update config successfully'
,
'status'
=>
'success'
]);
}
public
function
render
()
{
return
view
(
'livewire.pages.user.config-manual-response'
);
}
public
function
backToMainList
()
{
//Use emitTo() to call function on specific component, (emit() will call function on every loaded compoment)
$this
->
emitTo
(
'pages.user.user-index'
,
'showUserList'
,
''
);
}
public
function
testConnection
()
{
//Use emitTo() to call function on specific component, (emit() will call function on every loaded compoment)
$userConnect
=
UsersConnectSpn
::
where
(
'uid'
,
$this
->
editUserId
)
->
first
();
if
(
!
isset
(
$userConnect
)){
$this
->
dispatchBrowserEvent
(
'open-modal'
,
[
'name'
=>
'alert-modal'
,
'message'
=>
'SPN config is not found!'
,
'status'
=>
'failed'
]);
return
;
}
$spnConfigController
=
new
SpnConfigController
();
$spnConfig
=
$spnConfigController
->
init_connection
(
$userConnect
);
if
(
$spnConfig
!=
null
&&
$spnConfig
[
'success'
]
==
'true'
){
$this
->
dispatchBrowserEvent
(
'open-modal'
,
[
'name'
=>
'alert-modal'
,
'message'
=>
'Connect to SPN successfully'
,
'status'
=>
'success'
]);
}
else
if
(
$spnConfig
!=
null
&&
$spnConfig
[
'success'
]
==
'false'
){
$this
->
dispatchBrowserEvent
(
'open-modal'
,
[
'name'
=>
'alert-modal'
,
'message'
=>
$spnConfig
[
'message'
],
'status'
=>
'failed'
]);
}
else
{
//Cannot get UID/UCODE from SPN
$this
->
dispatchBrowserEvent
(
'open-modal'
,
[
'name'
=>
'alert-modal'
,
'message'
=>
'Cannot connect to SPN'
,
'status'
=>
'failed'
]);
}
}
}
app/Http/Livewire/Pages/User/UserIndex.php
View file @
a4b0f3d1
...
...
@@ -82,6 +82,17 @@ class UserIndex extends Component
$this
->
editUserId
=
$UserId
;
}
public
function
showConfigManualResponseForm
(
$UserId
)
{
if
(
!
Auth
::
user
()
->
hasPermissions
([
'edit-user'
]))
{
$this
->
showNoPermissionModal
=
TRUE
;
return
;
}
$this
->
action
=
'configManualResponse'
;
$this
->
editUserId
=
$UserId
;
}
public
function
hideMessage
()
{
$this
->
showMessage
=
false
;
...
...
app/Models/ManualResponse/DeclarationRunning.php
0 → 100644
View file @
a4b0f3d1
<?php
namespace
App\Models\ManualResponse
;
use
Illuminate\Database\Eloquent\Factories\HasFactory
;
use
Illuminate\Database\Eloquent\Model
;
class
DeclarationRunning
extends
Model
{
use
HasFactory
;
protected
$table
=
'mr_declaration_running'
;
protected
$fillable
=
[
'document_type'
,
'running_number'
,
'last_updated_date'
];
}
app/Models/ManualResponse/MasterDocTypes.php
0 → 100644
View file @
a4b0f3d1
<?php
namespace
App\Models\ManualResponse
;
use
Illuminate\Database\Eloquent\Factories\HasFactory
;
use
Illuminate\Database\Eloquent\Model
;
class
MasterDocTypes
extends
Model
{
use
HasFactory
;
protected
$table
=
'mr_master_doc_types'
;
}
app/Models/ManualResponse/MasterMessages.php
0 → 100644
View file @
a4b0f3d1
<?php
namespace
App\Models\ManualResponse
;
use
Illuminate\Database\Eloquent\Factories\HasFactory
;
use
Illuminate\Database\Eloquent\Model
;
class
MasterMessages
extends
Model
{
use
HasFactory
;
protected
$table
=
'mr_master_messages'
;
}
app/Models/ManualResponse/MasterResponseTemplates.php
0 → 100644
View file @
a4b0f3d1
<?php
namespace
App\Models\ManualResponse
;
use
Illuminate\Database\Eloquent\Factories\HasFactory
;
use
Illuminate\Database\Eloquent\Model
;
class
MasterResponseTemplates
extends
Model
{
use
HasFactory
;
protected
$table
=
'mr_master_response_templates'
;
}
app/Models/ManualResponse/TabManualResponseLog.php
0 → 100644
View file @
a4b0f3d1
<?php
namespace
App\Models\ManualResponse
;
use
Illuminate\Database\Eloquent\Factories\HasFactory
;
use
Illuminate\Database\Eloquent\Model
;
class
TabManualResponseLog
extends
Model
{
use
HasFactory
;
protected
$table
=
'mr_tab_manual_response_log'
;
protected
$fillable
=
[
'uid'
,
'title'
,
'detail'
,
'xml_content'
,
'reference_number'
,
'declaration_number'
,
'link'
,
];
}
app/Models/ManualResponse/UsersConnectSpn.php
0 → 100644
View file @
a4b0f3d1
<?php
namespace
App\Models\ManualResponse
;
use
Illuminate\Database\Eloquent\Factories\HasFactory
;
use
Illuminate\Database\Eloquent\Model
;
class
UsersConnectSpn
extends
Model
{
use
HasFactory
;
protected
$table
=
'mr_users_connect_spn'
;
protected
$fillable
=
[
'uid'
,
'username'
,
'password'
,
'link'
,
];
protected
$hidden
=
[
'password'
];
}
config/database.php
View file @
a4b0f3d1
...
...
@@ -60,6 +60,7 @@ return [
'engine'
=>
null
,
'options'
=>
extension_loaded
(
'pdo_mysql'
)
?
array_filter
([
PDO
::
MYSQL_ATTR_SSL_CA
=>
env
(
'MYSQL_ATTR_SSL_CA'
),
PDO
::
ATTR_PERSISTENT
=>
true
,
])
:
[],
],
...
...
resources/js/app.js
View file @
a4b0f3d1
...
...
@@ -88,18 +88,24 @@ Alpine.data('accordionItem', accordionItem);
Alpine
.
start
();
document
.
addEventListener
(
'
DOMContentLoaded
'
,
(
event
)
=>
{
Prism
.
highlightAll
();
document
.
addEventListener
(
'
DOMContentLoaded
'
,
async
(
event
)
=>
{
//Prism.highlightAll();
hljs
.
highlightAll
();
});
document
.
addEventListener
(
'
livewire:load
'
,
function
()
{
Prism
.
highlightAll
();
document
.
addEventListener
(
'
livewire:load
'
,
async
function
()
{
//Prism.highlightAll();
hljs
.
highlightAll
();
});
Livewire
.
hook
(
'
message.processed
'
,
(
message
,
component
)
=>
{
Prism
.
highlightAll
();
// Find all code blocks inside the component that was updated
component
.
el
.
querySelectorAll
(
'
pre
'
).
forEach
((
block
)
=>
{
hljs
.
highlightElement
(
block
);
// Apply syntax highlighting to the specific element
});
});
window
.
addEventListener
(
'
diffResultUpdated
'
,
function
()
{
Prism
.
highlightAll
();
window
.
addEventListener
(
'
diffResultUpdated
'
,
async
function
()
{
//Prism.highlightAll();
hljs
.
highlightAll
();
});
\ No newline at end of file
resources/views/components/modals/alert-modal.blade.php
0 → 100644
View file @
a4b0f3d1
@
props
([
'name'
,
'message'
=>
''
,
'status'
=>
''
])
<
div
x
-
data
=
"{ showModal: false, name: '{{
$name
}}', message: '{{
$message
}}', status: '{{
$status
}}' }"
x
-
show
=
"showModal"
x
-
on
:
open
-
modal
.
window
=
"if (
$event
.detail.name === name) { showModal = true; message =
$event
.detail.message; status =
$event
.detail.status; }"
x
-
on
:
close
-
modal
.
window
=
"showModal = false"
style
=
"display: none"
>
<
div
>
<
div
class
=
"fixed inset-0 z-[100] flex flex-col items-center justify-center overflow-hidden px-4 py-6 sm:px-5"
x
-
show
=
"showModal"
role
=
"dialog"
@
keydown
.
window
.
escape
=
"showModal = false"
>
<
div
class
=
"absolute inset-0 bg-slate-900/60 transition-opacity duration-300"
@
click
=
"showModal = false"
x
-
show
=
"showModal"
x
-
transition
:
enter
=
"ease-out"
x
-
transition
:
enter
-
start
=
"opacity-0"
x
-
transition
:
enter
-
end
=
"opacity-100"
x
-
transition
:
leave
=
"ease-in"
x
-
transition
:
leave
-
start
=
"opacity-100"
x
-
transition
:
leave
-
end
=
"opacity-0"
></
div
>
<
div
class
=
"relative max-w-lg min-w-[500px] rounded-lg bg-white px-4 py-10 text-center transition-opacity duration-300 dark:bg-navy-700 sm:px-5"
x
-
show
=
"showModal"
x
-
transition
:
enter
=
"ease-out"
x
-
transition
:
enter
-
start
=
"opacity-0"
x
-
transition
:
enter
-
end
=
"opacity-100"
x
-
transition
:
leave
=
"ease-in"
x
-
transition
:
leave
-
start
=
"opacity-100"
x
-
transition
:
leave
-
end
=
"opacity-0"
>
<!--
Conditional
SVGs
based
on
status
-->
<
template
x
-
if
=
"status === 'success'"
>
<
svg
xmlns
=
"http://www.w3.org/2000/svg"
class
=
"inline size-28 text-success"
fill
=
"none"
viewBox
=
"0 0 24 24"
stroke
=
"currentColor"
>
<
path
stroke
-
linecap
=
"round"
stroke
-
linejoin
=
"round"
stroke
-
width
=
"2"
d
=
"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
></
path
>
</
svg
>
</
template
>
<
template
x
-
if
=
"status === 'warning'"
>
<
svg
xmlns
=
"http://www.w3.org/2000/svg"
class
=
"inline size-28 text-warning"
fill
=
"none"
viewBox
=
"0 0 24 24"
stroke
=
"currentColor"
>
<
path
stroke
-
linecap
=
"round"
stroke
-
linejoin
=
"round"
stroke
-
width
=
"2"
d
=
"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
/>
</
svg
>
</
template
>
<
template
x
-
if
=
"status === 'failed'"
>
<
svg
xmlns
=
"http://www.w3.org/2000/svg"
class
=
"inline size-28 text-error"
viewBox
=
"0 0 20 20"
fill
=
"currentColor"
>
<
path
fill
-
rule
=
"evenodd"
d
=
"M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z"
clip
-
rule
=
"evenodd"
/>
</
svg
>
</
template
>
<
div
class
=
"mt-4"
>
<
p
class
=
"mt-2"
x
-
text
=
"message"
></
p
>
<
button
@
click
=
"showModal = false"
class
=
"btn mt-6 bg-gray-200 font-medium text-gray-700 hover:bg-gray-200-focus focus:bg-gray-200-focus active:bg-gray-200-focus/90"
>
Close
</
button
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
resources/views/components/modals/confirm-modal.blade.php
0 → 100644
View file @
a4b0f3d1
@
props
([
'name'
])
<
div
x
-
data
=
"{ showModal: false, name: '{{
$name
}}' }"
x
-
show
=
"showModal"
x
-
on
:
open
-
modal
.
window
=
"showModal = (
$event
.detail.name === name); console.log(event.detail)"
x
-
on
:
close
-
modal
.
window
=
"showModal = false"
style
=
"display: none"
>
<
template
x
-
teleport
=
"#x-teleport-target"
>
<
div
class
=
"fixed inset-0 z-[100] flex flex-col items-center justify-center overflow-hidden px-4 py-6 sm:px-5"
x
-
show
=
"showModal"
role
=
"dialog"
@
keydown
.
window
.
escape
=
"showModal = false"
>
<
div
class
=
"absolute inset-0 bg-slate-900/60 transition-opacity duration-300"
@
click
=
"showModal = false"
x
-
show
=
"showModal"
x
-
transition
:
enter
=
"ease-out"
x
-
transition
:
enter
-
start
=
"opacity-0"
x
-
transition
:
enter
-
end
=
"opacity-100"
x
-
transition
:
leave
=
"ease-in"
x
-
transition
:
leave
-
start
=
"opacity-100"
x
-
transition
:
leave
-
end
=
"opacity-0"
></
div
>
<
div
class
=
"relative max-w-lg min-w-[500px] rounded-lg bg-white px-4 py-10 text-center transition-opacity duration-300 dark:bg-navy-700 sm:px-5"
x
-
show
=
"showModal"
x
-
transition
:
enter
=
"ease-out"
x
-
transition
:
enter
-
start
=
"opacity-0"
x
-
transition
:
enter
-
end
=
"opacity-100"
x
-
transition
:
leave
=
"ease-in"
x
-
transition
:
leave
-
start
=
"opacity-100"
x
-
transition
:
leave
-
end
=
"opacity-0"
>
<
svg
xmlns
=
"http://www.w3.org/2000/svg"
class
=
"inline size-28 text-success"
fill
=
"none"
viewBox
=
"0 0 24 24"
stroke
=
"currentColor"
>
<
path
stroke
-
linecap
=
"round"
stroke
-
linejoin
=
"round"
stroke
-
width
=
"2"
d
=
"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
></
path
>
</
svg
>
<
div
class
=
"mt-4"
>
<
h2
class
=
"text-2xl text-slate-700 dark:text-navy-100"
></
h2
>
@
if
(
isset
(
$message
))
<
p
class
=
"mt-2"
>
{{
$message
}}
</
p
>
@
endif
<
button
@
click
=
"showModal = false"
class
=
"btn mt-6 font-medium text-slate-700 hover:bg-slate-300/20 active:bg-slate-300/25 border border-slate-300"
>
Cancel
</
button
>
<
button
@
click
=
"
$wire
.emit('test') ; showModal = false"
class
=
"btn mt-6 bg-primary font-medium text-white hover:bg-primary-focus focus:bg-primary-focus active:bg-primary-focus/90"
>
Confirm
</
button
>
</
div
>
</
div
>
</
div
>
</
template
>
</
div
>
resources/views/components/sidebar.blade.php
View file @
a4b0f3d1
...
...
@@ -97,6 +97,16 @@
</li>
</ul>
</div>
<div
class=
"rounded-2xl p-3 bg-white w-full mb-2"
>
<ul
>
<li
class=
"mb-1"
>
<a
href=
"/manual-response/index"
:class=
"activeLink === '/manual-response/index' ? 'bg-primary-focus text-white rounded-xl' : 'text-black'"
class=
"block py-2 px-4 rounded text-black flex items-center"
>
<i
aria-hidden=
"true"
class=
"fa-sharp fa-regular fa-paper-plane mr-2"
></i>
Manual Response
</a>
</li>
</ul>
</div>
<div
class=
"rounded-2xl p-3 bg-white w-full mb-2"
x-data=
"{ open: ['/company', '/role', '/group', '/user', '/format-file-master'].includes(activeLink) }"
>
<ul
>
...
...
resources/views/livewire/loading-component.blade.php
0 → 100644
View file @
a4b0f3d1
<div>
<div
wire:loading
wire:target=
"{{ $action }}"
style=
"display: none"
>
<div
class=
"fixed inset-0 z-[100] flex flex-col items-center justify-center overflow-hidden px-4 py-6 sm:px-5"
>
<div
class=
"absolute inset-0 bg-slate-200/60 backdrop-blur transition-opacity duration-300"
>
</div>
<div
class=
"spinner size-16 animate-spin rounded-full border-4 border-[#A020F0] border-r-transparent dark:border-accent dark:border-r-transparent"
>
</div>
</div>
</div>
</div>
resources/views/livewire/main-container.blade.php
View file @
a4b0f3d1
...
...
@@ -82,9 +82,14 @@
<livewire:pages.report.report-index
wire:init
/>
@break
@case('ManualResponse')
<livewire:pages.manual-response.manual-response/>
@break
@default
@livewire('code-comparer')
@endswitch
<x-modals.alert-modal
name=
"alert-modal"
></x-modals.alert-modal>
</div>
<script>
// document.addEventListener('livewire:load', function () {
...
...
resources/views/livewire/pages/manual-response/manual-response-index.blade.php
0 → 100644
View file @
a4b0f3d1
<div>
<div
id=
"backgroundDiv"
class=
"w-11/12 mx-auto mt-5 mb-5 pb-5 bg-white/20 rounded-lg shadow-lg backdrop-blur-sm border border-white/30"
>
<div
class=
"w-10/12 mx-auto pt-5"
id=
"filterDiv"
>
@if ($errors->any())
{{ $displayCustomizeDiv = false }}
@endif
<h1
class=
"text-2xl font-bold tracking-tight text-gray-900"
>
Manual Response: Standard Template
</h1>
<hr
class=
"my-5"
>
<div
class=
"badge space-x-2.5 rounded-full bg-primary text-white shadow-soft shadow-lg shadow-[#1f863680]/50 p-2.5 mb-2"
>
<div
class=
"size-2 rounded-full bg-current mr-1"
></div>
Step 1: Config
</div>
<div
class=
"mx-auto"
>
<div
class=
"grid grid-cols-1 gap-4 sm:grid-cols-3 pb-1"
>
<label
class=
"block"
>
<span
class=
"block text-sm font-medium text-slate-700"
>
Message
</span>
<span
class=
"relative mt-1.5 mb-0.1 flex"
>
<select
class=
"form-select h-9 w-full rounded-lg border border-slate-300 bg-white px-3 py-2 hover:border-slate-400 focus:border-primary dark:border-navy-450 dark:bg-navy-700 dark:hover:border-navy-400 dark:focus:border-accent"
wire:model=
"messageId"
>
<option
value=
""
>
Select an option
</option>
@foreach ($messageTypes as $value => $label)
<option
value=
"{{ $value }}"
>
{{ $label }}
</option>
@endforeach
</select>
</span>
@error('messageId')
<span
class=
"text-tiny+ text-error"
>
{{ $message }}
</span>
@enderror
</label>
<label
class=
"block"
>
<span
class=
"block text-sm font-medium text-slate-700"
>
Template
</span>
<span
class=
"relative mt-1.5 mb-0.1 flex"
>
<select
class=
"form-select h-9 w-full rounded-lg border border-slate-300 bg-white px-3 py-2 hover:border-slate-400 focus:border-primary dark:border-navy-450 dark:bg-navy-700 dark:hover:border-navy-400 dark:focus:border-accent"
wire:model.defer=
"templateId"
>
<option
value=
""
>
Select an option
</option>
@foreach ($responseTemplates as $value => $label)
<option
value=
"{{ $value }}"
>
{{ $label }}
</option>
@endforeach
</select>
</span>
@error('templateId')
<span
class=
"text-tiny+ text-error"
>
{{ $message }}
</span>
@enderror
</label>
<label
class=
"block"
>
<span
class=
"block text-sm font-medium text-slate-700"
>
Document Type
</span>
<span
class=
"relative mt-1.5 mb-0.1 flex"
>
<select
class=
"form-select h-9 w-full rounded-lg border border-slate-300 bg-white px-3 py-2 hover:border-slate-400 focus:border-primary dark:border-navy-450 dark:bg-navy-700 dark:hover:border-navy-400 dark:focus:border-accent"
wire:model.defer=
"docType"
>
<option
value=
""
>
Select an option
</option>
@foreach ($docTypes as $value => $label)
<option
value=
"{{ $value }}"
>
{{ $label }}
</option>
@endforeach
</select>
</span>
@error('docType')
<span
class=
"text-tiny+ text-error"
>
{{ $message }}
</span>
@enderror
</label>
</div>
<div
class=
"flex justify-center items-center py-1"
>
<button
class=
"bg-primary text-white hover:bg-primary-focus py-2 px-4 rounded-md mr-1"
wire:click=
"gotoCustomize"
>
<i
class=
"fa-solid fa-arrow-right mr-1"
></i>
Customize
</button>
<label
class=
"inline-flex items-center space-x-2"
>
<input
class=
"form-checkbox is-basic size-5 rounded border-slate-400/70 checked:bg-primary checked:border-primary hover:border-primary focus:border-primary dark:border-navy-400 dark:checked:bg-accent dark:checked:border-accent dark:hover:border-accent dark:focus:border-accent"
type=
"checkbox"
wire:model.defer=
"lockData"
@
if
($
disableLockData
)
disabled
@
endif
/>
<p>
Lock Data
</p>
</label>
</div>
</div>
</div>
@if ($displayCustomizeDiv)
<div
class=
"w-10/12 mx-auto"
id=
"customizeResponseDiv"
>
<hr
class=
"my-5"
>
{{--
<h1
class=
"text-2xl font-bold tracking-tight text-gray-900"
>
1. Customize Template
</h1>
--}}
<div
class=
"badge space-x-2.5 rounded-full bg-primary text-white shadow-soft shadow-lg shadow-[#1f863680]/50 p-2.5 mb-2"
>
<div
class=
"size-2 rounded-full bg-current mr-1"
></div>
Step 2: Customize
</div>
@if (session()->has('error'))
<div
x-data=
"{ show: {{ session()->has('error') ? 'true' : 'false' }} }"
x-init=
"setTimeout(() => show = false, 2000)"
x-show=
"show"
x-transition:leave=
"transition ease-in duration-1000"
x-transition:leave-start=
"opacity-100"
x-transition:leave-end=
"opacity-0"
class=
"alert flex rounded-lg bg-error px-4 py-4 text-white sm:px-5"
>
{{ session('error') }}
</div>
@endif
<div
class=
"flex"
>
<div
class=
"w-4/12"
>
<div
class=
"w-12/12 py-1"
>
@foreach ($xmlData as $key => $value)
<label
class=
"block"
>
<span
class=
"text-sm font-medium text-slate-700"
>
{{ $key }}
</span>
<span
class=
"relative mt-1.5 mb-1.5 flex"
>
<input
class=
"form-input peer w-full rounded-lg border border-slate-300 px-3 py-2 placeholder:text-slate-400/70 hover:border-slate-400 focus:border-primary dark:border-navy-450 dark:hover:border-navy-400 dark:focus:border-accent"
type=
"text"
id=
"{{ $key }}"
wire:model=
"xmlData.{{ $key }}"
value=
"{{ $value }}"
autocomplete=
"off"
/>
</span>
</label>
@endforeach
</div>
</div>
<div
class=
"w-8/12 pl-5"
>
<div>
<span
class=
"block text-sm font-medium text-slate-700"
>
Preview XML
</span>
</div>
<div
class=
"bg-gray-100 p-4 rounded-lg"
>
<!-- Highlight.js Code Block -->
<pre
class=
"is-scrollbar-hidden max-h-96 overflow-auto rounded-lg"
x-data
x-init=
"hljs.highlightElement($el);"
><code
class=
"xml"
>
{{ $xmlContent }}
</code></pre>
</div>
<div
class=
"flex justify-center items-center pt-1"
>
<button
class=
"bg-slate-150 font-medium text-slate-800 hover:bg-slate-200 focus:bg-slate-200 active:bg-slate-200/80 rounded-md border border-[#e5e7eb] py-2 px-4 mr-1"
wire:click=
"reGenerateXML"
>
<i
class=
"fa-solid fa-rotate mr-1"
></i>
Reload XML
</button>
</div>
</div>
</div>
<div
class=
"flex justify-center items-center py-1"
>
<button
class=
"bg-primary text-white hover:bg-primary-focus font-bold py-2 px-4 rounded-md mr-1"
wire:click=
"generateAndUploadXml"
></i>
Submit
</button>
</div>
</div>
@endif
@include('livewire.loading-component', ['action' => 'generateAndUploadXml, messageId'])
</div>
</div>
Prev
1
2
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment