From 53950459e24f718637c56a66590c9288bf1284e7 Mon Sep 17 00:00:00 2001 From: Jia Sheng Date: Tue, 6 Aug 2024 22:33:07 +0800 Subject: [PATCH 01/11] show warning on manual po, add periodic 1688 manual po --- .../bookings/forms/PurchaseOrderFormComponent.vue | 13 +++++++++++-- .../sections/BookingDetailsSectionComponent.vue | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue b/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue index b9a0f2d6..30daf141 100644 --- a/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue +++ b/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue @@ -1,5 +1,5 @@ - +
From eecb351fb38d03e3de188fe4fee245ee98b271dc Mon Sep 17 00:00:00 2001 From: edmondlang Date: Fri, 23 Aug 2024 16:59:05 +0800 Subject: [PATCH 06/11] fix proforma invoice --- ...ateProformaInvoiceTransactionProcessor.php | 63 +++++++++++-------- .../pages/pdfs/proforma_invoice.blade.php | 5 ++ 2 files changed, 43 insertions(+), 25 deletions(-) diff --git a/app/Classes/Modules/Transactions/Processors/CreateProformaInvoiceTransactionProcessor.php b/app/Classes/Modules/Transactions/Processors/CreateProformaInvoiceTransactionProcessor.php index 1a48fc31..28a34057 100644 --- a/app/Classes/Modules/Transactions/Processors/CreateProformaInvoiceTransactionProcessor.php +++ b/app/Classes/Modules/Transactions/Processors/CreateProformaInvoiceTransactionProcessor.php @@ -24,6 +24,7 @@ use App\Classes\ValueObjects\Constants\DocumentType; use App\Models\Booking; use App\Models\Document; use Carbon\Carbon; +use Illuminate\Support\Facades\Log; use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf; class CreateProformaInvoiceTransactionProcessor @@ -102,32 +103,44 @@ class CreateProformaInvoiceTransactionProcessor */ public function execute(Booking $booking) { - $po_order_transaction = $booking->transactions() ->where('type', TransactionType::PURCHASE_ORDER) ->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED]) ->first(); - $outstanding = $this->calculatesBookingOutstanding->execute($booking); - - $conversionObject = new CurrencyConversionObject(floatval(str_replace(',', '', $outstanding)), $booking->convertible_currency_id, $booking->service_id, $booking->fix_currency_id === 1 ? 0:1, PaymentMethodType::CASH); - - $configurations = $this->fetchesBookingQuotation->execute($booking->company, $conversionObject); - - $paymentAttemptLimit = $this->fetchesCompanyPaymentAttemptLimit->execute($booking->company); - - $billNumber = $this->generatesTransactionBillNumber->execute('PYMT-'); - $transaction = $booking->transactions() ->where('type', TransactionType::PAYMENT) ->first(); if (!$transaction) { - $object = new TransactionObject($billNumber, TransactionType::PAYMENT, 1, $booking->company->id, - $configurations->getConfigurations()->getBankId(), $configurations->getConversionObject()->getPaymentMethod(), - $configurations->getTotal(), $configurations->getForeignTotal(), 1, - $configurations->getConversionObject()->getCurrencyId(), $configurations->getConfigurations()->getRate(), - $configurations->getTax(), $configurations->getServiceCharge(), Carbon::now()->addMinutes($paymentAttemptLimit), ApprovalStatus::PENDING_SUBMISSION, [], isset($billPlzBill) ? $billPlzBill->id : NULL + $outstanding = $this->calculatesBookingOutstanding->execute($booking); + + $conversionObject = new CurrencyConversionObject(floatval(str_replace(',', '', $outstanding)), $booking->convertible_currency_id, $booking->service_id, $booking->fix_currency_id === 1 ? 0 : 1, PaymentMethodType::CASH); + + $configurations = $this->fetchesBookingQuotation->execute($booking->company, $conversionObject); + + $paymentAttemptLimit = $this->fetchesCompanyPaymentAttemptLimit->execute($booking->company); + + $billNumber = $this->generatesTransactionBillNumber->execute('PYMT-'); + + $object = new TransactionObject( + $billNumber, + TransactionType::PAYMENT, + 1, + $booking->company->id, + $configurations->getConfigurations()->getBankId(), + $configurations->getConversionObject()->getPaymentMethod(), + $configurations->getTotal(), + $configurations->getForeignTotal(), + 1, + $configurations->getConversionObject()->getCurrencyId(), + $configurations->getConfigurations()->getRate(), + $configurations->getTax(), + $configurations->getServiceCharge(), + Carbon::now()->addMinutes($paymentAttemptLimit), + ApprovalStatus::PENDING_SUBMISSION, + [], + isset($billPlzBill) ? $billPlzBill->id : NULL ); $this->createsTransaction->execute($booking, $object); @@ -135,10 +148,10 @@ class CreateProformaInvoiceTransactionProcessor $billNumber = $this->generatesTransactionBillNumber->execute('PROFORMA-'); - $payable_amount = $booking->transactions()->payments()->where(function($query){ - return $query->where(function($query){ + $payable_amount = $booking->transactions()->payments()->where(function ($query) { + return $query->where(function ($query) { return $query->where('status', ApprovalStatus::PENDING_SUBMISSION)->whereDate('expires_on', '>=', Carbon::now())->where('expires_on', '>', Carbon::now()->toTimeString()); - })->orWhere(function($query){ + })->orWhere(function ($query) { return $query->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); }); })->sum('amount'); @@ -148,14 +161,16 @@ class CreateProformaInvoiceTransactionProcessor ->where('type', TransactionType::PAYMENT) ->first(); - $booking_currency_average_rate = $booking_amount / $booking->transactions()->payments()->where(function($query){ - return $query->where(function($query){ + $paymentAmount = $booking->transactions()->payments()->where(function ($query) { + return $query->where(function ($query) { return $query->where('status', ApprovalStatus::PENDING_SUBMISSION)->whereDate('expires_on', '>=', Carbon::now())->where('expires_on', '>', Carbon::now()->toTimeString()); - })->orWhere(function($query){ + })->orWhere(function ($query) { return $query->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); }); })->selectRaw('sum(amount - service_charge - tax) as sub_total')->get()->sum('sub_total'); + $booking_currency_average_rate = $booking_amount / $paymentAmount; + $total_service_charge = $booking->transactions() ->where('type', TransactionType::PAYMENT) ->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::SUSPENDED]) @@ -196,7 +211,7 @@ class CreateProformaInvoiceTransactionProcessor $purchase_order_pdf = LaravelMpdf::loadView('pages.pdfs.proforma_invoice', ['invoice_transaction' => $proforma_transaction, 'po_order_transaction' => $po_order_transaction, 'supplier' => $supplier]); $document_object = new DocumentObject( DocumentType::PROFORMA_INVOICE, - [chunk_split('data:application/pdf;base64,'.base64_encode($purchase_order_pdf->output()))], + [chunk_split('data:application/pdf;base64,' . base64_encode($purchase_order_pdf->output()))], '', ApprovalStatus::COMPLETED, 'proforma_invoices' @@ -205,7 +220,5 @@ class CreateProformaInvoiceTransactionProcessor /** @var Document $document */ $document = $this->createsDocument->execute($po_order_transaction->booking, $document_object); $this->createsFile->execute($document, $document_object); - - } } diff --git a/resources/views/pages/pdfs/proforma_invoice.blade.php b/resources/views/pages/pdfs/proforma_invoice.blade.php index da5e8238..6d25b5ba 100644 --- a/resources/views/pages/pdfs/proforma_invoice.blade.php +++ b/resources/views/pages/pdfs/proforma_invoice.blade.php @@ -70,6 +70,11 @@

+ + @include('pages.pdfs.purchase_order_table') From b7fd252bf0b8db46226d6ba182fae32afec40370 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Sun, 25 Aug 2024 12:43:33 +0800 Subject: [PATCH 07/11] Voucherify - New promotion voucher (PROM150%) setup --- .../Services/FetchesBookingQuotation.php | 14 ++-- .../CheckMilestonesForRewardProcessor.php | 2 +- .../ControllersLogic/ValidateVoucherLogic.php | 14 ++-- .../DataTransferObjects/VoucherObject.php | 15 ++++- .../Processors/CreateVoucherProcessor.php | 9 ++- .../BookingToVoucherifyProcessor.php | 16 +++-- .../Vouchers/Services/CreatesVoucher.php | 1 + .../ValueObjects/Constants/Vouchers.php | 2 + app/Http/Resources/VoucherResource.php | 1 + ...3025_add_description_to_vouchers_table.php | 32 +++++++++ .../elements/AvailableVouchersComponent.vue | 6 +- .../BookingPaymentQuotationComponent.vue | 4 +- .../SingleUserRewardItemComponent.vue | 67 +++++++++++++------ .../AddVoucherOptionsSectionComponent.vue | 2 +- 14 files changed, 136 insertions(+), 49 deletions(-) create mode 100644 database/migrations/2024_08_24_173025_add_description_to_vouchers_table.php diff --git a/app/Classes/Modules/Bookings/Services/FetchesBookingQuotation.php b/app/Classes/Modules/Bookings/Services/FetchesBookingQuotation.php index feafba19..a1291207 100644 --- a/app/Classes/Modules/Bookings/Services/FetchesBookingQuotation.php +++ b/app/Classes/Modules/Bookings/Services/FetchesBookingQuotation.php @@ -73,12 +73,14 @@ class FetchesBookingQuotation $employeeWhoOwnsTheVoucher = null; $employees = $company->first()->employees; - foreach($employees as $singleEmployee){ - $userRewards = $singleEmployee->rewards; - foreach($userRewards as $userReward){ - if ($userReward->voucher && $userReward->voucher->code === $voucherCode) { - Log::info('1. Company with multiple employees: ' . json_encode($singleEmployee) . ", voucher: " . $voucherCode); - $employeeWhoOwnsTheVoucher = $singleEmployee; + if(count($employees) > 1){ + foreach($employees as $singleEmployee){ + $userRewards = $singleEmployee->rewards; + foreach($userRewards as $userReward){ + if ($userReward->voucher && $userReward->voucher->code === $voucherCode) { + Log::info('1. Company with multiple employees: ' . json_encode($singleEmployee) . ", voucher: " . $voucherCode); + $employeeWhoOwnsTheVoucher = $singleEmployee; + } } } } diff --git a/app/Classes/Modules/Milestones/Processors/CheckMilestonesForRewardProcessor.php b/app/Classes/Modules/Milestones/Processors/CheckMilestonesForRewardProcessor.php index bda5ba5a..23eb27b3 100644 --- a/app/Classes/Modules/Milestones/Processors/CheckMilestonesForRewardProcessor.php +++ b/app/Classes/Modules/Milestones/Processors/CheckMilestonesForRewardProcessor.php @@ -149,7 +149,7 @@ class CheckMilestonesForRewardProcessor $voucherEndDate = $result->expiration_date; //create voucher - $voucherObject = new VoucherObject($result->code, isset($voucherName) ? $voucherName : "", $voucherType, $voucherValue, null, $voucherStartDate, $voucherEndDate); + $voucherObject = new VoucherObject($result->code, isset($voucherName) ? $voucherName : "", null, $voucherType, $voucherValue, null, $voucherStartDate, $voucherEndDate); $voucher = $this->createsVoucher->execute($voucherObject); if(!$voucher) $voucher = $this->fetchesVoucher->execute(['code' => $voucherObject->getCode()]); $voucherId = $voucher->id; diff --git a/app/Classes/Modules/Vouchers/ControllersLogic/ValidateVoucherLogic.php b/app/Classes/Modules/Vouchers/ControllersLogic/ValidateVoucherLogic.php index 4530292f..41b2724d 100644 --- a/app/Classes/Modules/Vouchers/ControllersLogic/ValidateVoucherLogic.php +++ b/app/Classes/Modules/Vouchers/ControllersLogic/ValidateVoucherLogic.php @@ -47,12 +47,14 @@ class ValidateVoucherLogic extends AbstractControllerLogic $booking = Booking::find($request->input('itemId')); $employees = $booking->company->employees()->get(); - foreach($employees as $singleEmployee){ - $userRewards = $singleEmployee->rewards; - foreach($userRewards as $userReward){ - if ($userReward->voucher && $userReward->voucher->code === $request->input('voucherCode')) { - Log::info('2. Company with multiple employees: ' . json_encode($singleEmployee) . ", voucher: " . $request->input('voucherCode')); - $employeeWhoOwnsTheVoucher = $singleEmployee; + if(count($employees) > 1){ + foreach($employees as $singleEmployee){ + $userRewards = $singleEmployee->rewards; + foreach($userRewards as $userReward){ + if ($userReward->voucher && $userReward->voucher->code === $request->input('voucherCode')) { + Log::info('2. Company with multiple employees: ' . json_encode($singleEmployee) . ", voucher: " . $request->input('voucherCode')); + $employeeWhoOwnsTheVoucher = $singleEmployee; + } } } } diff --git a/app/Classes/Modules/Vouchers/DataTransferObjects/VoucherObject.php b/app/Classes/Modules/Vouchers/DataTransferObjects/VoucherObject.php index 78f67dfe..70564b7f 100644 --- a/app/Classes/Modules/Vouchers/DataTransferObjects/VoucherObject.php +++ b/app/Classes/Modules/Vouchers/DataTransferObjects/VoucherObject.php @@ -15,6 +15,9 @@ class VoucherObject implements DataTransferObject /** @var string|null */ private $name; + /** @var string|null */ + private $description; + /** @var string|null */ private $type; @@ -34,16 +37,18 @@ class VoucherObject implements DataTransferObject * VoucherObject constructor. * @param string $code * @param string $name + * @param string $description * @param string $type * @param float $value * @param int $voucherCampaignId * @param string $startDate * @param string $endDate */ - public function __construct(string $code, ?string $name, ?string $type, ?float $value, ?int $voucherCampaignId, ?string $startDate = '', ?string $endDate = '') + public function __construct(string $code, ?string $name, ?string $description, ?string $type, ?float $value, ?int $voucherCampaignId, ?string $startDate = '', ?string $endDate = '') { $this->code = $code; $this->name = $name; + $this->description = $description; $this->type = $type; $this->value = $value; $this->voucherCampaignId = $voucherCampaignId; @@ -67,6 +72,14 @@ class VoucherObject implements DataTransferObject return $this->name; } + /** + * @return string + */ + public function getDescription(): ?string + { + return $this->description; + } + /** * @return string */ diff --git a/app/Classes/Modules/Vouchers/Processors/CreateVoucherProcessor.php b/app/Classes/Modules/Vouchers/Processors/CreateVoucherProcessor.php index 1026a330..92a3a484 100644 --- a/app/Classes/Modules/Vouchers/Processors/CreateVoucherProcessor.php +++ b/app/Classes/Modules/Vouchers/Processors/CreateVoucherProcessor.php @@ -48,6 +48,8 @@ class CreateVoucherProcessor public function execute(?User $user, string $voucherCodeInput, ?int $campaignId = null) { //Remotely - Get Voucher Voucherify $voucherifyVoucherFetched = $this->fetchesVoucherifyVoucher->execute($user, $voucherCodeInput); + $voucherName = null; + $voucherDescription = null; //Voucher stored locally need a name, by default use campaign name, else look into campaign metadata for displayname if(isset($voucherifyVoucherFetched->metadata) && isset($voucherifyVoucherFetched->metadata->displayname)){ @@ -57,6 +59,10 @@ class CreateVoucherProcessor $voucherName = $voucherifyVoucherFetched->campaign; } + if(isset($voucherifyVoucherFetched->metadata) && isset($voucherifyVoucherFetched->metadata->display_description)){ + $voucherDescription = $voucherifyVoucherFetched->metadata->display_description; + } + $voucherType = $voucherifyVoucherFetched->discount->type; $voucherValue = isset($voucherifyVoucherFetched->discount->amount_off) ? $voucherifyVoucherFetched->discount->amount_off : $voucherifyVoucherFetched->discount->percent_off; $voucherCode = $voucherifyVoucherFetched->code; @@ -66,7 +72,8 @@ class CreateVoucherProcessor //Locally - Create and Fetch Voucher $voucherObject = new VoucherObject( $voucherCode, - isset($voucherName) ? $voucherName : "Voucher ".Carbon::now()->format('Ymd'), + $voucherName ?? "Voucher ".Carbon::now()->format('Ymd'), + $voucherDescription, $voucherType, $voucherValue, $campaignId, diff --git a/app/Classes/Modules/Vouchers/Processors/Voucherify/BookingToVoucherifyProcessor.php b/app/Classes/Modules/Vouchers/Processors/Voucherify/BookingToVoucherifyProcessor.php index 90fba55a..c4d959d2 100644 --- a/app/Classes/Modules/Vouchers/Processors/Voucherify/BookingToVoucherifyProcessor.php +++ b/app/Classes/Modules/Vouchers/Processors/Voucherify/BookingToVoucherifyProcessor.php @@ -86,12 +86,14 @@ class BookingToVoucherifyProcessor $employeeWhoOwnsTheVoucher = null; $employees = $user->company()->first()->employees; - foreach($employees as $singleEmployee){ - $userRewards = $singleEmployee->rewards; - foreach($userRewards as $userReward){ - if ($userReward->voucher && $userReward->voucher->code === $voucherCode) { - Log::info('3. Company with multiple employees: ' . json_encode($singleEmployee) . ", voucher: " . $voucherCode); - $employeeWhoOwnsTheVoucher = $singleEmployee; + if(count($employees) > 1){ + foreach($employees as $singleEmployee){ + $userRewards = $singleEmployee->rewards; + foreach($userRewards as $userReward){ + if ($userReward->voucher && $userReward->voucher->code === $voucherCode) { + Log::info('3. Company with multiple employees: ' . json_encode($singleEmployee) . ", voucher: " . $voucherCode); + $employeeWhoOwnsTheVoucher = $singleEmployee; + } } } } @@ -151,7 +153,7 @@ class BookingToVoucherifyProcessor $voucherCampaign = VoucherCampaign::where('campaign_id', $voucherifyCampaignId)->first(); } - $voucherObject= new VoucherObject($redeemedVoucher->code, isset($redeemedVoucher->metadata->displayname) ? $redeemedVoucher->metadata->displayname : "", $voucherType, $voucherValue, $voucherCampaign ? $voucherCampaign->id : null); + $voucherObject= new VoucherObject($redeemedVoucher->code, isset($redeemedVoucher->metadata->displayname) ? $redeemedVoucher->metadata->displayname : "", null, $voucherType, $voucherValue, $voucherCampaign ? $voucherCampaign->id : null); $voucher = $this->createsVoucher->execute($voucherObject); if(!$voucher) $voucher = $this->fetchesVoucher->execute(['code' => $voucherObject->getCode()]); diff --git a/app/Classes/Modules/Vouchers/Services/CreatesVoucher.php b/app/Classes/Modules/Vouchers/Services/CreatesVoucher.php index 3622036a..88a9a133 100644 --- a/app/Classes/Modules/Vouchers/Services/CreatesVoucher.php +++ b/app/Classes/Modules/Vouchers/Services/CreatesVoucher.php @@ -31,6 +31,7 @@ class CreatesVoucher extends AbstractUpdateRecord $model = new Voucher(); $model->code = $object->getCode(); $model->name = $object->getName(); + $model->description = $object->getDescription(); $model->type = $object->getType(); $model->value = $object->getValue(); $model->voucher_campaign_id = $object->getVoucherCampaignId(); diff --git a/app/Classes/ValueObjects/Constants/Vouchers.php b/app/Classes/ValueObjects/Constants/Vouchers.php index 0e870182..4c6c8bb1 100644 --- a/app/Classes/ValueObjects/Constants/Vouchers.php +++ b/app/Classes/ValueObjects/Constants/Vouchers.php @@ -9,10 +9,12 @@ final class Vouchers { public const SORRY_50 = 'SORRY50'; public const SORRY_100 = 'SORRY100'; public const SORRY_200 = 'SORRY200'; + public const PROM150PERCENT = 'PROM150%'; const OPTIONS_SORRY = [ ['text' => 'SORRY 50', 'id' => Vouchers::SORRY_50], ['text' => 'SORRY 100', 'id' => Vouchers::SORRY_100], ['text' => 'SORRY 200', 'id' => Vouchers::SORRY_200], + ['text' => 'PROM150%', 'id' => Vouchers::PROM150PERCENT], ]; } diff --git a/app/Http/Resources/VoucherResource.php b/app/Http/Resources/VoucherResource.php index 55cc2b56..f4315bd1 100644 --- a/app/Http/Resources/VoucherResource.php +++ b/app/Http/Resources/VoucherResource.php @@ -30,6 +30,7 @@ class VoucherResource extends JsonResource return [ 'id' => $this->id, 'name' => $this->name, + 'description' => $this->description, 'code' => $this->code, 'type' => $this->type, 'value' => (float) $this->value, diff --git a/database/migrations/2024_08_24_173025_add_description_to_vouchers_table.php b/database/migrations/2024_08_24_173025_add_description_to_vouchers_table.php new file mode 100644 index 00000000..6dde0c8a --- /dev/null +++ b/database/migrations/2024_08_24_173025_add_description_to_vouchers_table.php @@ -0,0 +1,32 @@ +text('description')->after('name')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('vouchers', function (Blueprint $table) { + $table->dropColumn('description'); + }); + } +} diff --git a/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue b/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue index 0d52ff13..9737309b 100644 --- a/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue +++ b/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue @@ -9,9 +9,9 @@
RM{{ item.voucher.value/100 }} Discount
- +
+ 50% Discount +
diff --git a/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue b/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue index ba2d7893..ab1cd074 100644 --- a/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue +++ b/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue @@ -246,9 +246,9 @@
- + Apply a voucher
diff --git a/resources/assets/vue/components/companies/elements/SingleUserRewardItemComponent.vue b/resources/assets/vue/components/companies/elements/SingleUserRewardItemComponent.vue index 9cc2409a..c7b78466 100644 --- a/resources/assets/vue/components/companies/elements/SingleUserRewardItemComponent.vue +++ b/resources/assets/vue/components/companies/elements/SingleUserRewardItemComponent.vue @@ -1,29 +1,54 @@