Compare commits

..

19 Commits

Author SHA1 Message Date
edmondlang bcfeb49275 update address extra fields 2024-07-18 00:14:19 +08:00
edmondlang b4c6e721fd Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into address-extra-fields 2024-07-17 23:29:51 +08:00
edmondlang aa65b333c8 update permits reminder 2024-07-17 18:13:50 +08:00
edmondlang 656c50e047 update permits reminder 2024-07-17 18:11:34 +08:00
edmondlang 275157b243 update permits reminder 2024-07-17 17:49:33 +08:00
edmondlang 0c9ffd2bf7 call wac webhook 2024-07-06 11:24:54 +08:00
edmondlang a953f78771 update address extra fields 2024-07-05 01:18:36 +08:00
edmondlang cf3e7f04e4 Merge branches 'master' and 'address-extra-fields' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into address-extra-fields 2024-07-05 00:26:12 +08:00
edmondlang be0cd16285 update address extra fields 2024-07-05 00:25:57 +08:00
edmondlang d4dcae155d add command to fix missing packinglist 2024-07-03 12:56:16 +08:00
edmondlang bad8cadb3a remove edmond email from permits reminder 2024-07-02 21:12:52 +08:00
edmondlang 3af32cc6e7 remove command fix missing packinglist 2024-07-02 20:57:27 +08:00
edmondlang 34bab6a45c fix missing packinglist 2024-07-02 20:52:06 +08:00
edmondlang dd1eae1ea2 fix missing packinglist 2024-07-02 13:02:16 +08:00
Dillon Ngo b46bfb38bf Merge branch 'dillon/62.3-fixes' into 'master'
Quick fix on https://izyim.cief-malaysia.com/order/show/245904319

See merge request CIEFWorldwideSdnBhd/shipping-portal!233
2024-07-01 07:01:20 +00:00
edmondlang 2f55821046 add multi select 2024-06-24 23:13:48 +08:00
edmondlang 4a9ac3de02 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into address-extra-fields 2024-06-20 10:03:57 +08:00
edmondlang 1e6fafef28 make address line 2 required 2024-06-20 10:02:15 +08:00
edmondlang 9d0924c674 address extra fields 2024-06-12 12:02:31 +08:00
21 changed files with 365 additions and 43 deletions
@@ -36,6 +36,8 @@ use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
class CreateCustomerLogic extends AbstractControllerLogic
{
@@ -167,6 +169,18 @@ class CreateCustomerLogic extends AbstractControllerLogic
CreatePerfexCRMCustomer::dispatch($createLeadPerfexCRMObject);
}
if(!app()->environment(['production'])){
// call wac webhook
$url = 'https://wacontact.readyspace.com/rest/trigger/9fe03daf-2ace-4095-b064-601ef6d9bfe7';
$payload = [
'name' => $request->input('name'),
'email' => $request->input('email'),
'phone' => $request->input('phone'),
];
$response = Http::post($url, $payload);
Log::channel('wac_webhook')->info(json_encode($response));
}
// $this->generateEmailVerificationAttemptProcessor->execute($user);
return $this->response($this->authenticationProcessor->execute($request));
@@ -15,6 +15,7 @@ use App\Classes\Modules\Contacts\Processors\CreateContactProcessor;
use App\Classes\Modules\Remarks\DataTransferObjects\RemarkObject;
use App\Classes\Modules\Remarks\Processors\CreateRemarkProcessor;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\RemarkTypes;
use App\Http\Resources\AddressResource;
use App\Models\Address;
use ErrorException;
@@ -100,6 +101,16 @@ class CreateAddressLogic extends AbstractControllerLogic
$this->createRemarkProcessor->execute($address, $remarkObject);
}
$addressExtraFields = [
'property_type' => $request->input('property_type'),
'tools_required_unload' => $request->input('tools_required_unload'),
'pickup_time_from' => $request->input('pickup_time_from'),
'pickup_time_to' => $request->input('pickup_time_to'),
];
$addressExtraFieldsObject = new RemarkObject(json_encode($addressExtraFields), Auth()->user()->id, RemarkTypes::ADDRESS_EXTRA_COLUMNS);
$this->createRemarkProcessor->execute($address, $addressExtraFieldsObject);
return $this->resourceResponse(new AddressResource($address));
}
@@ -15,10 +15,12 @@ use App\Classes\Modules\Remarks\DataTransferObjects\RemarkObject;
use App\Classes\Modules\Remarks\Processors\CreateRemarkProcessor;
use App\Classes\ValueObjects\Constants\AddressType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\RemarkTypes;
use App\Http\Resources\AddressResource;
use App\Models\Address;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Carbon\Carbon;
class UpdateAddressLogic extends AbstractControllerLogic
{
@@ -102,6 +104,25 @@ class UpdateAddressLogic extends AbstractControllerLogic
$this->createRemarkProcessor->execute($address, $remarkObject);
}
if ($request->input('pickup_time_to') <= $request->input('pickup_time_from')) {
$pickupTimeFrom = Carbon::parse($request->input('pickup_time_from'));
$request->merge([
'pickup_time_to' => $pickupTimeFrom->addHour()->format('H:i') // Format to hh:mm
]);
}
$addressExtraFields = [
'property_type' => $request->input('property_type'),
'additional_request' => $request->input('additional_request'),
'receive_goods_working_hours' => $request->input('receive_goods_working_hours'),
'receive_goods_after_hours' => $request->input('receive_goods_after_hours'),
'receive_goods_on_saturday' => $request->input('receive_goods_on_saturday'),
];
$address->addressExtraFields()->delete();
$addressExtraFieldsObject = new RemarkObject(json_encode($addressExtraFields), Auth()->user()->id, RemarkTypes::ADDRESS_EXTRA_COLUMNS);
$this->createRemarkProcessor->execute($address, $addressExtraFieldsObject);
return $this->resourceResponse(new AddressResource($address));
}
@@ -138,7 +138,13 @@ class FetchPackingListsFromYdPortalProcessor
$receiveDate = Carbon::parse(substr(preg_replace("/[^0-9]/", "", $row->expressno), 0, 8));
$customerno = preg_split('(-|\(|\)|\/)', $row->customerno);
$customerno = $row->customerno;
// Check if $customerno contains '正确唛头YD' and extract the part after it
if (strpos($customerno, '正确唛头YD') !== false) {
$customerno = explode('正确唛头YD', $customerno)[1];
}
$customerno = preg_split('/[-()\/]/', $customerno);
$orderNumber = $customerno[array_key_last($customerno)];
$allow_contract = true;
@@ -13,10 +13,14 @@ class RemarkObject implements DataTransferObject
/** @var string*/
private $content;
public function __construct(string $content, int $commenterID)
/** @var int|null */
private $type;
public function __construct(string $content, int $commenterID, int $type = null)
{
$this->commenterID = $commenterID;
$this->content = $content;
$this->type = $type;
}
/**
@@ -35,4 +39,12 @@ class RemarkObject implements DataTransferObject
return $this->content;
}
/**
* @return int|null
*/
public function getType(): ?int
{
return $this->type;
}
}
@@ -24,6 +24,7 @@ class CreatesRemark extends AbstractUpdateRelationshipRecord
$model->commenter_id = $object->getCommenterId();
$model->content = $object->getContent();
$model->type = $object->getType();
return $this->handler($remarkable->remarks(), $model);
@@ -10,4 +10,6 @@ final class RemarkTypes
public const EXTERNAL = 1;
}
public const ADDRESS_EXTRA_COLUMNS = 2;
}
@@ -0,0 +1,54 @@
<?php
namespace App\Console\Commands;
use App\Classes\Modules\PackingLists\Processors\FetchPackingListsFromYdPortalProcessor;
use Carbon\Carbon;
use Illuminate\Console\Command;
class FixMissingPackingList extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'fix-missing-packinglist';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Fix Missing Packinglist';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$start_date = '2024-05-05';
$end_date = '2024-05-05';
$start = $start_date ? Carbon::parse($start_date) : null;
$end = $end_date ? Carbon::parse($end_date) : null;
if (!$start || !$end) {
return;
}
(App()->make(FetchPackingListsFromYdPortalProcessor::class))->execute($start, $end);
}
}
@@ -76,7 +76,7 @@ class SendPermitsReminderEmails extends Command
protected function getEmailList(): array
{
return [
'edmond.wuiming2021@gmail.com',
// 'edmond.wuiming2021@gmail.com',
'anithagurl96@gmail.com'
];
}
@@ -40,25 +40,41 @@ class ImportPermitsReminderController
$row['reminder_date'] = $this->changeExcelDate($row['reminder_date']);
$validator = Validator::make($row, [
'model' => 'required|unique:permits_reminders,model',
'expiry_date' => 'required|date|after_or_equal:today',
'reminder_date' => 'required|date|after_or_equal:today',
'model' => 'required',
// 'expiry_date' => 'required|date|after_or_equal:today',
'expiry_date' => 'required|date',
// 'reminder_date' => 'required|date|after_or_equal:today',
'reminder_date' => 'required|date',
]);
if ($validator->fails()) {
$row['status'] = 'failed';
$row['message'] = $validator->errors()->all();
$returnArray[] = $row;
} else {
$row['created_at'] = Carbon::now();
$row['updated_at'] = Carbon::now();
$successRows[] = $row;
$existingRecord = PermitsReminder::where('model', $row['model'])->first();
if ($existingRecord) {
$existingRecord->update([
'expiry_date' => $row['expiry_date'],
'reminder_date' => $row['reminder_date'],
]);
$row['status'] = 'Updated';
$row['message'] = 'Record has been updated';
$returnArray[] = $row;
} else {
// Add to successful rows for batch insertion
$row['created_at'] = Carbon::now();
$row['updated_at'] = Carbon::now();
$successRows[] = $row;
}
}
}
// Insert only if there are new successful rows
if (!empty($successRows)) {
PermitsReminder::insert($successRows); // Insert only if there are successful rows
PermitsReminder::insert($successRows);
}
$successCount = count($successRows);
+12 -1
View File
@@ -27,7 +27,11 @@ class AddressResource extends JsonResource
$outstationPostcodeConstant = $outstationPostcodeConstantObject->isEmpty() ? [] : (array)$outstationPostcodeConstantObject->first()->value;
in_array((String)$this->postcode, $outstationPostcodeConstant) ? $postcodeArea = 'OUTSTATION_POSTCODE' : null;
return [
// Handle extra fields
$extrafields = $this->addressExtraFields->first();
$extrafields = $extrafields ? json_decode($extrafields->content, true) : [];
$returnArray = [
'id' => $this->id,
'reference' => $this->reference,
'street_one' => $this->street_one,
@@ -52,5 +56,12 @@ class AddressResource extends JsonResource
])
];
// Merge extra fields into the return array
if ($extrafields) {
$returnArray = array_merge($returnArray, $extrafields);
}
return $returnArray;
}
}
+2 -1
View File
@@ -5,6 +5,7 @@ namespace App\Http\Resources;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\OrderRoleTypes;
use App\Classes\ValueObjects\Constants\PackingListType;
use App\Classes\ValueObjects\Constants\RemarkTypes;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\TransportType;
use App\Models\Transaction;
@@ -53,7 +54,7 @@ class OrderResource extends JsonResource
'invoices' => $this->whenLoaded('packingLists', function() use ($orderId) {
return TransactionResource::collection($this->transactions()->whereNotIn('transactions.status', [0, 1])->where('transactions.type', TransactionType::SHIPPING_INVOICE)->get());
}),
'remarks' => RemarkResource::collection($this->remarks),
'remark' => new RemarkResource($this->remarks->first()),
'created_at' => $this->created_at->format('d-m-Y')
];
+10 -1
View File
@@ -4,6 +4,7 @@ namespace App\Models;
use App\Classes\General\Interfaces\Contactable;
use App\Classes\General\Interfaces\Remarkable;
use App\Classes\ValueObjects\Constants\RemarkTypes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOne;
@@ -87,6 +88,14 @@ class Address extends AbstractModel implements Contactable, Remarkable
*/
public function remarks(): morphMany
{
return $this->morphMany(Remark::class, 'owner');
return $this->morphMany(Remark::class, 'owner')->whereNull('type');
}
/**
* @return MorphMany
*/
public function addressExtraFields(): MorphMany
{
return $this->morphMany(Remark::class, 'owner')->where('type', RemarkTypes::ADDRESS_EXTRA_COLUMNS);
}
}
+5
View File
@@ -130,6 +130,11 @@ return [
'path' => storage_path('logs/laravel_perfex_crm.log'),
'level' => 'info',
],
'wac_webhook' => [
'driver' => 'single',
'path' => storage_path('logs/wac_webhook.log'),
'level' => 'info',
],
],
];
@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddTypeToRemarksTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('remarks', function (Blueprint $table) {
$table->string('type')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('remarks', function (Blueprint $table) {
$table->dropColumn('type');
});
}
}
+1
View File
@@ -31,6 +31,7 @@
"vue": "^2.6.10",
"vue-avatar": "^2.1.8",
"vue-debounce": "^2.6.0",
"vue-multi-select": "^4.6.0",
"vue-template-compiler": "^2.6.10",
"vue-the-mask": "^0.11.1",
"vuelidate": "^0.7.4",
@@ -3,14 +3,6 @@
<div class="col">
<div class="row" v-if="![7,8].includes($store.getters.getCompanyModuleType)">
<div class="col">
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.reference">
<label>Address Reference/Label</label>
<input class="form-control" name="reference" v-model="parameters.reference">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.street_one">
@@ -41,6 +33,14 @@
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.reference">
<label>Address Name / Label</label>
<input class="form-control" name="reference" v-model="parameters.reference" placeholder="E.g. Home Address">
</validation-wrapper-component>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
@@ -59,14 +59,6 @@
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.remark">
<label>Delivery Remark</label>
<input class="form-control" name="remark" v-model="parameters.remark">
</validation-wrapper-component>
</div>
</div>
</div>
</div>
</div>
@@ -125,16 +117,70 @@
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.remark">
<label>Remark</label>
<input class="form-control" name="remark" v-model="parameters.remark">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.remark">
<label>Delivery Remark</label>
<input class="form-control" name="remark" v-model="parameters.remark">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component selectable :validator="$v.parameters.property_type">
<label>房型 Receiver's property type</label>
<select-component :options="['住家Landed house', '公寓Condominium (Drop on lobby only)', '工厂Factory', '店面Shop', '商场Shopping Mall (Drop on loading bay only)', 'Others']" v-model="parameters.property_type"></select-component>
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<div class="form-group no-margin form-group-default p-b-5">
<label>Available to receive goods on: </label>
<div class="row">
<div class="col-12 col-md pb-3 pb-md-0">
<div class="row justify-content-center m-t-10 m-b-10" @click="parameters.receive_goods_working_hours = !parameters.receive_goods_working_hours">
<div class="col pointer d-flex justtify-content-center align-items-center">
<i class="fa fs-20 fa-fw m-r-5" :class="{'fa-square-o': !parameters.receive_goods_working_hours, 'fa-check-square': parameters.receive_goods_working_hours, 'text-primary':parameters.receive_goods_working_hours}" ></i>
<p class="m-b-0">Working Hours (9am-6pm)</p>
</div>
</div>
</div>
<div class="col-12 col-md pb-3 pb-md-0">
<div class="row justify-content-center m-t-10 m-b-10" @click="parameters.receive_goods_after_hours = !parameters.receive_goods_after_hours">
<div class="col pointer d-flex justtify-content-center align-items-center">
<i class="fa fs-20 fa-fw m-r-5" :class="{'fa-square-o': !parameters.receive_goods_after_hours, 'fa-check-square': parameters.receive_goods_after_hours, 'text-primary':parameters.receive_goods_after_hours}" ></i>
<p class="m-b-0">After Working Hours</p>
</div>
</div>
</div>
<div class="col-12 col-md pb-3 pb-md-0">
<div class="row justify-content-center m-t-10 m-b-10" @click="parameters.receive_goods_on_saturday = !parameters.receive_goods_on_saturday">
<div class="col pointer d-flex justtify-content-center align-items-center">
<i class="fa fs-20 fa-fw m-r-5" :class="{'fa-square-o': !parameters.receive_goods_on_saturday, 'fa-check-square': parameters.receive_goods_on_saturday, 'text-primary':parameters.receive_goods_on_saturday}" ></i>
<p class="m-b-0">On Saturday</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.additional_request">
<label>Additional Request</label>
<input class="form-control" name="additional_request" v-model="parameters.additional_request">
</validation-wrapper-component>
</div>
</div>
<div class="row justify-content-center allign-items-center">
<div class="col-12 col-sm-7">
<h6 class="text-center fs-12 text-danger">**kindly reply within 2 hours while warehouse contact to arrange for delivery, otherwise, reschedule of delivery date will apply</h6>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
@@ -154,7 +200,7 @@
props: {
id: {
type: Number,
required: true
// required: true
},
type: {
type: Number,
@@ -174,6 +220,11 @@
remark: '',
phone: '',
person_in_charge: '',
property_type: '',
additional_request: '',
receive_goods_working_hours: false,
receive_goods_after_hours: false,
receive_goods_on_saturday: false,
}
}
@@ -189,6 +240,11 @@
this.parameters.phone = this.data.contact ? this.data.contact.phone : '';
this.parameters.person_in_charge = this.data.contact ? this.data.contact.reference : '';
this.parameters.remark = this.data.remark ? this.data.remark.content : '';
this.parameters.property_type = this.data.property_type ? this.data.property_type : '';
this.parameters.additional_request = this.data.additional_request ? this.data.additional_request : '';
this.parameters.receive_goods_working_hours = this.data.receive_goods_working_hours ? this.data.receive_goods_working_hours : false;
this.parameters.receive_goods_after_hours = this.data.receive_goods_after_hours ? this.data.receive_goods_after_hours : false;
this.parameters.receive_goods_on_saturday = this.data.receive_goods_on_saturday ? this.data.receive_goods_on_saturday : false;
}
},
watch: {
@@ -0,0 +1,67 @@
<template>
<div class="w-100 multi-select-container">
<vue-multi-select ref="multiSelect" v-model="localValue" search :options="settings" :btnLabel="btnLabel" :selectOptions="options" class="w-100" style="height: 25px;" @close="close">
<template v-slot:option="{ option }">
<div class="d-flex justify-content-start align-items-center">
<input class="m-l-5 m-r-5" type="checkbox" :checked="option.selected" />
<span>{{ option.name }}</span>
</div>
</template>
</vue-multi-select>
</div>
</template>
<script>
import vueMultiSelect from 'vue-multi-select';
import 'vue-multi-select/dist/lib/vue-multi-select.css';
import PerfectScrollbar from 'perfect-scrollbar';
export default {
props: {
value: {
type: Array,
required: false,
default: () => []
},
options: {
type: Array,
required: true
}
},
data() {
return {
localValue: this.value,
settings: {
multi: true,
groups: false,
},
};
},
methods: {
btnLabel(localValue) {
if (localValue.length === 0) {
return 'Please select';
}
return localValue.join(', ');
},
close() {
this.$emit('input', this.localValue);
}
},
components: {
vueMultiSelect,
PerfectScrollbar,
},
};
</script>
<style>
.multi-select-container .select>button {
width: 100%;
min-height: unset;
}
.multi-select-container .select .selectItem {
color: black !important;
}
</style>
@@ -10,15 +10,18 @@ export default {
},
street_one: { required },
street_two: {
required: requiredIf(function(){
return [7,8].includes(this.$store.getters.getCompanyModuleType);
})
required
// required: requiredIf(function(){
// return [7,8].includes(this.$store.getters.getCompanyModuleType);
// })
},
district_id: { required },
post_code: { required },
remark: {},
phone: {required, numeric},
person_in_charge: { required },
property_type: { required },
additional_request: { },
}
},
mixins: [addressFormHandler]
-2
View File
@@ -34,8 +34,6 @@ Route::group(['middleware' => 'api', 'prefix' => 'v1', 'as' => 'api.'], function
Route::post('/import/update-debtor/f614e339d7058904a831aad742e24d55', 'Imports\ImportUpdateDebtorController@import')->name('debtor.import');
Route::post('/import/upload-permits-reminder', 'Imports\ImportPermitsReminderController@import')->name('permits_reminder.upload');
require __DIR__ . '/company.php';
require __DIR__ . '/document.php';
+2
View File
@@ -9,3 +9,5 @@ Route::group(['prefix' => 'permits-reminder', 'as' => 'permits_reminder.', 'name
Route::post('/{id}/update', 'UpdatePermitsReminderController@update')->name('update');
});
Route::post('/import/upload-permits-reminder', 'Imports\ImportPermitsReminderController@import')->name('permits_reminder.upload');