diff --git a/app/Classes/General/Eloquent/Filters/HasActiveReward.php b/app/Classes/General/Eloquent/Filters/HasActiveReward.php index 5770ca6e..26385b96 100644 --- a/app/Classes/General/Eloquent/Filters/HasActiveReward.php +++ b/app/Classes/General/Eloquent/Filters/HasActiveReward.php @@ -2,7 +2,6 @@ namespace App\Classes\General\Eloquent\Filters; -use App\Classes\ValueObjects\Constants\RoleTypes; use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Facades\Auth; @@ -12,33 +11,17 @@ class HasActiveReward implements Filter /** * @param Builder $builder * @param $value - * @return mixed + * @return Builder|mixed */ public static function apply(Builder $builder, $value) { - if(in_array(Auth::user()->type, RoleTypes::ADMIN_ROLES)){ - // $userId = $value !== 1 ? $value : Auth::user()->id; - $userId = $value; - return $builder->where('user_id', $userId) - ->where(function ($query) { - $query->whereHas('reward', function ($subquery) { - $subquery->where('is_active', true); - }) - ->orWhereDoesntHave('reward'); - }) - ->whereDoesntHave('voucher.redemptions.transaction.booking.company.employees', function ($query) use ($userId) { - $query->where('user_id', $userId); + return $builder->where('user_id', Auth::user()->id) //cief todo: should not use Auth::user()->id + ->where(function ($query) { + $query->whereHas('reward', function ($subquery) { + $subquery->where('is_active', true); }); - } - else{ - return $builder->where('user_id', Auth::user()->id) - ->where(function ($query) { - $query->whereHas('reward', function ($subquery) { - $subquery->where('is_active', true); - }) - ->orWhereDoesntHave('reward'); - }) - ->whereDoesntHave('voucher.redemptions.transaction.owner'); - } + // ->orWhereDoesntHave('reward'); + }); } + } diff --git a/app/Classes/General/Eloquent/Filters/HasActiveRewardForAdmin.php b/app/Classes/General/Eloquent/Filters/HasActiveRewardForAdmin.php new file mode 100644 index 00000000..5d69aa4b --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/HasActiveRewardForAdmin.php @@ -0,0 +1,26 @@ +where('user_id', $value) + ->where(function ($query) { + $query->whereHas('reward', function ($subquery) { + $subquery->where('is_active', true); + }); + // ->orWhereDoesntHave('reward'); + }); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/HasVouchersAll.php b/app/Classes/General/Eloquent/Filters/HasVouchersAll.php new file mode 100644 index 00000000..d2ff7a2e --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/HasVouchersAll.php @@ -0,0 +1,44 @@ +type, RoleTypes::ADMIN_ROLES)){ + // $userId = $value !== 1 ? $value : Auth::user()->id; + $userId = $value; + return $builder->where('user_id', $userId) + ->where(function ($query) { + $query->whereHas('reward', function ($subquery) { + $subquery->where('is_active', true); + }) + ->orWhereDoesntHave('reward'); + }) + ->whereDoesntHave('voucher.redemptions.transaction.booking.company.employees', function ($query) use ($userId) { + $query->where('user_id', $userId); + }); + } + else{ + return $builder->where('user_id', Auth::user()->id) + ->where(function ($query) { + $query->whereHas('reward', function ($subquery) { + $subquery->where('is_active', true); + }) + ->orWhereDoesntHave('reward'); + }) + ->whereDoesntHave('voucher.redemptions.transaction.owner'); + } + } +} diff --git a/app/Classes/General/Open1688/SignatureUtil.php b/app/Classes/General/Open1688/SignatureUtil.php new file mode 100644 index 00000000..91c21005 --- /dev/null +++ b/app/Classes/General/Open1688/SignatureUtil.php @@ -0,0 +1,31 @@ + $v ) { + $paramToSign = $k . $v; + Array_push ( $paramsToSign, $paramToSign ); + } + sort ( $paramsToSign ); + $implodeParams = implode ( $paramsToSign ); + $pathAndParams = $path . $implodeParams; + $sign = hash_hmac ( "sha1", $pathAndParams, config('open1688.app_secret'), true ); + $signHexWithLowcase = bin2hex ( $sign ); + $signHexUppercase = strtoupper ( $signHexWithLowcase ); + return $signHexUppercase; + } +} + +?> \ No newline at end of file diff --git a/app/Classes/General/Open1688Helper.php b/app/Classes/General/Open1688Helper.php new file mode 100644 index 00000000..70bbf8eb --- /dev/null +++ b/app/Classes/General/Open1688Helper.php @@ -0,0 +1,79 @@ + "{\"keyword\":\"$keyword\",\"beginPage\":$page,\"pageSize\":18,\"country\":\"en\"}", + ]; + + return self::getFromOpen1688($requestData, config('open1688.product_search_keyword_api')); + } + + public static function productDetail($offerId) { + $requestData = [ + 'offerDetailParam' => "{\"offerId\":$offerId,\"country\":\"en\"}", + ]; + + return self::getFromOpen1688($requestData, config('open1688.product_detail_api')); + } + + private static function getFromOpen1688($requestData, $apiName) { + $requestData["access_token"] = config('open1688.access_token'); + + $signaturedStr = self::generateRequestSignature($apiName, $requestData); + $url = config('open1688.url') . $apiName . "/" . config('open1688.app_key') . "?_aop_signature=" . $signaturedStr; + + + foreach($requestData as $k => $v) { + $url = $url . "&$k=$v"; + } + + try { + $client = new \GuzzleHttp\Client(['verify' => false]); + $response = $client->request('GET', $url); + $body = $response->getBody(); + $contents = json_decode($body, true); + + return $contents['result']['result']; + } catch(\GuzzleHttp\Exception\RequestException $exception){ + throw new MalformedRequestException(json_decode($exception->getResponse()->getBody()->getContents(), true)['error_message']); + } + + } + + private static function generateRequestSignature ($apiName, $requestData) { + $pathToSign = self::generateAPIPath($apiName); + $signaturedStr = SignatureUtil::signature ($pathToSign, $requestData); + + return $signaturedStr; + } + + private static function generateAPIPath($apiName) { + $urlResult = ""; + $defs = array ( + $urlResult, + "param2", + "/", + "1", + "/", + "com.alibaba.fenxiao.crossborder", + "/", + $apiName, + "/", + config('open1688.app_key') + ); + + $urlResult = implode ( $defs ); + + return $urlResult; + } + +} diff --git a/app/Classes/Jobs/CreateMilestoneRewardByTransactionJob.php b/app/Classes/Jobs/CreateMilestoneRewardByTransactionJob.php new file mode 100644 index 00000000..86208cc9 --- /dev/null +++ b/app/Classes/Jobs/CreateMilestoneRewardByTransactionJob.php @@ -0,0 +1,38 @@ +transaction = $transaction; + $this->milestones = $milestones; + } + + public function handle() + { + (App()->make(MilestoneRewardByTransactionProcessor::class))->execute($this->transaction, $this->milestones); + } +} diff --git a/app/Classes/Modules/Accounting/ControllersLogic/ImportCiefLiteStatementLogic.php b/app/Classes/Modules/Accounting/ControllersLogic/ImportCiefLiteStatementLogic.php index 9a909d71..164cb142 100644 --- a/app/Classes/Modules/Accounting/ControllersLogic/ImportCiefLiteStatementLogic.php +++ b/app/Classes/Modules/Accounting/ControllersLogic/ImportCiefLiteStatementLogic.php @@ -7,6 +7,7 @@ use App\Classes\Exceptions\MalformedRequestException; use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject; use App\Classes\ValueObjects\Constants\ApprovalStatus; +use App\Classes\ValueObjects\Constants\StatementTransactionOwnerType; use App\Models\AccountStatement; use App\Models\StatementAccount; use App\Models\StatementTransaction; @@ -45,77 +46,28 @@ class ImportCiefLiteStatementLogic extends AbstractControllerLogic $sheet = $collection->first()->skip(1); - $dateTo = $sheet->first()[10]; - $dateFrom = $sheet->last()[10]; - $totalTransaction = $sheet->count(); - - $offset = 1; - do { - $dateFrom = $sheet->offsetGet($sheet->count() - $offset)[10]; - $offset += 1; - } while(!$dateFrom); - - - $dateFrom = carbon::parse($dateFrom); - $dateTo = carbon::parse($dateTo); - - $statement = AccountStatement::whereDate('date_from', $dateFrom) - ->whereDate('date_to', $dateTo) - ->where('total_amount', $totalTransaction) - ->first(); - - if(!$statement){ - $statement = new AccountStatement([ - 'date_from' => $dateFrom, - 'date_to' => $dateTo, - 'total_amount' => $totalTransaction, - ]); - } - - $account = StatementAccount::where("name", "CIEF LITE")->first(); - - if (!$account) { - throw new Exception("Statement Account for CIEF LITE not found."); - } - - $account->statements()->save($statement); - - $sheet->map(function ($row) use ($statement) { - if (!$row[0]) { + $sheet->map(function ($row) { + if (!$row[0] || trim($row[8]) !== "已审核") { return; } - $postingDate = $row[10]; - $transactionDescription = trim($row[1]); - $description2 = trim($row[2]); - $description3 = "Fee " . $row[6]; - $description4 = trim($row[8]); - $transactionRef = trim($row[12]); + $postingDate =date('Y-m-d', strtotime($row[10])); $amount = ((float) str_replace(',', '', $row[7])); - $transactionCode = $row[0]; - $transaction = new StatementTransaction([ - 'posting_date' => $postingDate, - 'transaction_description' => $transactionDescription, - 'transaction_description_2' => $description2, - 'transaction_description_3' => $description3, - 'transaction_description_4' => $description4, - 'transaction_ref' => $transactionRef, - 'amount' => $amount, - 'transaction_code' => $transactionCode, - ]); + + $statementTransaction = StatementTransaction::whereHas('account', function($query) { + $query->where('statement_accounts.number', 8881040198515); + })->whereDate('posting_date', $postingDate)->where('amount', $amount)->first(); - // Check if the transaction already exists for this statement - $existingTransaction = StatementTransaction::where('transaction_ref', $transactionRef) - ->where('posting_date', $postingDate) - ->where('amount', $amount) - ->where('transaction_description', $transactionDescription) - ->where('transaction_code', $transactionCode) - ->first(); - - if (!$existingTransaction) { - $statement->transactions()->save($transaction); + if (!$statementTransaction) { + return; } - return $transaction; + $owner = $statementTransaction->owners()->firstOrCreate([ + 'type' => StatementTransactionOwnerType::WALLET_TOP_UP, + 'system' => 'LITE', + 'owner_reference'=> $row[0], + ]); + + return $owner; }); } diff --git a/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php b/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php index d86e0bf7..9a155f74 100644 --- a/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php +++ b/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php @@ -12,7 +12,6 @@ use App\Classes\Modules\Companies\Processors\AssignEmployeeProcessor; use App\Classes\Modules\Companies\Processors\AssignSegmentProcessor; use App\Classes\Modules\Companies\Processors\CreateCompanyProcessor; use App\Classes\Modules\Contacts\Processors\CreateContactProcessor; -use App\Classes\Modules\Milestones\Processors\CheckMilestonesForRewardProcessor; use App\Classes\Modules\Vouchers\Processors\Voucherify\NewCustomerToVoucherifyProcessor; use App\Classes\Modules\Vouchers\Processors\CreateVoucherProcessor; use App\Classes\Modules\Companies\DataTransferObjects\EmploymentObject; @@ -74,9 +73,6 @@ class CreateCustomerLogic extends AbstractControllerLogic /** @var CreatesSeasonalSegment */ private $createsSeasonalSegment; - /** @var CheckMilestonesForRewardProcessor */ - private $checkMilestonesForRewardProcessor; - /** @var NewCustomerToVoucherifyProcessor */ private $newCustomerToVoucherifyProcessor; @@ -100,14 +96,13 @@ class CreateCustomerLogic extends AbstractControllerLogic * @param GenerateEmailVerificationAttemptProcessor $generateEmailVerificationAttemptProcessor * @param AssignSegmentProcessor $assignCompanyToSegmentProcessor * @param CreatesSeasonalSegment $createsSeasonalSegment - * @param CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor * @param NewCustomerToVoucherifyProcessor $newCustomerToVoucherifyProcessor * @param CreateVoucherProcessor $createVoucherProcessor * @param RegisterOnShippingProcessor $registerOnShippingProcessor * @param ConnectCompanyToShippingCompanyModule $connectCompanyToShippingCompanyModule */ public function __construct(CreateUserProcessor $createUserProcessor, CreateCompanyProcessor $createCompanyProcessor, CreateContactProcessor $createContactProcessor, AssignEmployeeProcessor $assignEmployeeProcessor, AssignSegmentProcessor $assignSegmentProcessor, AuthenticationProcessor $authenticationProcessor, GenerateEmailVerificationAttemptProcessor $generateEmailVerificationAttemptProcessor, - CreatesSeasonalSegment $createsSeasonalSegment, CheckMilestonesForRewardProcessor $checkMilestonesForRewardProcessor, NewCustomerToVoucherifyProcessor $newCustomerToVoucherifyProcessor, CreateVoucherProcessor $createVoucherProcessor, RegisterOnShippingProcessor $registerOnShippingProcessor, ConnectCompanyToShippingCompanyModule $connectCompanyToShippingCompanyModule) + CreatesSeasonalSegment $createsSeasonalSegment, NewCustomerToVoucherifyProcessor $newCustomerToVoucherifyProcessor, CreateVoucherProcessor $createVoucherProcessor, RegisterOnShippingProcessor $registerOnShippingProcessor, ConnectCompanyToShippingCompanyModule $connectCompanyToShippingCompanyModule) { $this->createUserProcessor = $createUserProcessor; $this->createCompanyProcessor = $createCompanyProcessor; @@ -118,7 +113,6 @@ class CreateCustomerLogic extends AbstractControllerLogic $this->generateEmailVerificationAttemptProcessor = $generateEmailVerificationAttemptProcessor; $this->assignCompanyToSegmentProcessor = $assignSegmentProcessor; $this->createsSeasonalSegment = $createsSeasonalSegment; - $this->checkMilestonesForRewardProcessor = $checkMilestonesForRewardProcessor; $this->newCustomerToVoucherifyProcessor = $newCustomerToVoucherifyProcessor; $this->createVoucherProcessor = $createVoucherProcessor; $this->registerOnShippingProcessor = $registerOnShippingProcessor; diff --git a/app/Classes/Modules/Accounts/Processors/AuthenticationProcessor.php b/app/Classes/Modules/Accounts/Processors/AuthenticationProcessor.php index 952bebdd..7e5fca53 100644 --- a/app/Classes/Modules/Accounts/Processors/AuthenticationProcessor.php +++ b/app/Classes/Modules/Accounts/Processors/AuthenticationProcessor.php @@ -81,8 +81,8 @@ class AuthenticationProcessor $this->newCustomerToVoucherifyProcessor->execute(0, $user, false); } - //cief todo: case study 1 voucherify - //$this->checkMilestonesForRewardProcessor->execute($user, [Milestones::MILESTONE_1]); + //cief todo: case study 1 + //$this->checkMilestonesForRewardProcessor->execute($user, [Milestones::MILESTONE_DEMO_1]); return ['access_token' => $this->generatesAuthenticationToken->execute($user), 'redirect_url' => $this->authenticationRedirect->url($user)]; } diff --git a/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php b/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php index 186ef3b6..a6d48a5e 100644 --- a/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php +++ b/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php @@ -27,6 +27,7 @@ use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Log; use App\Classes\Modules\Wallets\Services\RecalculatesWalletBalance; + class CallbackBillplzLogic { @@ -55,7 +56,9 @@ class CallbackBillplzLogic * @param FetchesTransaction $fetchesTransaction * @param UpdatesTransactionStatus $updatesTransactionStatus * @param UpdatesWalletBalance $updatesWalletBalance + * @param CreateCashBackTransactionProcessor $createCashBackTransactionProcessor * @param RecalculatesWalletBalance $recalculatesWalletBalance + * @param CreateMilestoneRewardJob $createMilestoneRewardJob */ public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, UpdatesWalletBalance $updatesWalletBalance, CreateCashBackTransactionProcessor $createCashBackTransactionProcessor, RecalculatesWalletBalance $recalculatesWalletBalance) { @@ -117,4 +120,4 @@ class CallbackBillplzLogic return $request->method() === 'POST' ? true : view('pages.payments_redirect', ['marking' => $marking ?? null, 'transaction' => $transaction, 'status' => $status]); } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php index 6b6adc16..c652e773 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php @@ -115,9 +115,7 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic $conversionObject = $this->createConversionObject($request, $booking); - $outstanding = $this->calculatesBookingOutstanding->execute($booking); - - if($conversionObject->getAmount() > round($outstanding, 2)) throw new MalformedRequestException('Your payment must not be greater than '. $outstanding .'.'); + $this->validatePayment($request, $booking, $conversionObject); $configurations = $this->fetchBookingQuotation->execute($booking->company, $conversionObject, $request->input('voucher_code')); @@ -138,6 +136,10 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic $this->updatesTransactionStatus->execute($transaction, ApprovalStatus::PENDING_VERIFICATION); } + if(PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')] == PaymentMethodType::WALLET){ + $this->updatesTransactionStatus->execute($transaction, ApprovalStatus::APPROVED); + } + return $this->resourceResponse(new TransactionResource($transaction)); } @@ -154,7 +156,7 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic private function validatePayment(Request $request, Booking $booking, CurrencyConversionObject $conversionObject): void { - $outstanding = $this->calculatesBookingOutstanding->execute($booking); + $outstanding = $this->calculatesBookingOutstanding->execute($booking) + $this->calculatesBookingRefundAmount->execute($booking, $booking->fix_currency_id); if($conversionObject->getAmount() > round($outstanding, 2)) throw new MalformedRequestException('Your payment must not be greater than '. $outstanding .'.'); diff --git a/app/Classes/Modules/Milestones/Processors/CheckMilestonesForRewardProcessor.php b/app/Classes/Modules/Milestones/Processors/CheckMilestonesForRewardProcessor.php index 597fa8bc..1a138dfa 100644 --- a/app/Classes/Modules/Milestones/Processors/CheckMilestonesForRewardProcessor.php +++ b/app/Classes/Modules/Milestones/Processors/CheckMilestonesForRewardProcessor.php @@ -81,9 +81,12 @@ class CheckMilestonesForRewardProcessor try{ foreach($milestone_constants as $constant) { - //update milestone progress - /** @var Milestone $milestone */ - $milestone = $this->fetchesMilestone->execute(['name' => $constant]); + //update milestone progres + $milestone = Milestone::where('name', $constant)->first(); + if(!$milestone) { + Log::error("{$constant} NOT FOUND!"); + continue; + } $result = null; if($user->milestoneProgress->count() > 0){ $result = $user->milestoneProgress->where('milestone_id', $milestone->id)->first(); @@ -130,6 +133,10 @@ class CheckMilestonesForRewardProcessor //Voucherify - Create Voucher $result = $this->createsVoucherifyVoucher->execute($user, intval($reward->value)); } + else if($reward->type == RewardType::REWARD_CODE){ + //Voucherify - Get Voucher + $result = $this->fetchesVoucherifyVoucher->execute($user, $reward->value); + } else{ //Voucherify - Validates Voucher $ValidateVoucherifyVoucherObject = new ValidateVoucherifyVoucherObject(0, $reward->value, 0.00, $user); diff --git a/app/Classes/Modules/Milestones/Processors/MilestoneRewardByTransactionProcessor.php b/app/Classes/Modules/Milestones/Processors/MilestoneRewardByTransactionProcessor.php new file mode 100644 index 00000000..ea9abf9c --- /dev/null +++ b/app/Classes/Modules/Milestones/Processors/MilestoneRewardByTransactionProcessor.php @@ -0,0 +1,48 @@ +checkMilestonesForRewardProcessor = $checkMilestonesForRewardProcessor; + } + + + /** + * @param Transaction $transaction + * @param array $milestones + * @throws \App\Classes\Exceptions\AccessForbiddenException + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function execute(Transaction $transaction, array $milestones) + { + $company = $transaction->owner instanceof Booking ? $transaction->owner()->first()->company : null; + if($company){ + $completedBookingCount = count($company->bookings()->where('status', ApprovalStatus::COMPLETED)->get()); + Log::info("Number of completed bookings completed for company ".$company->reference. ": " .$completedBookingCount); + if (in_array(Milestones::MILESTONE_1, $milestones)) { + if($completedBookingCount === 2){ + $user = $company->employees()->first(); + $this->checkMilestonesForRewardProcessor->execute($user, [Milestones::MILESTONE_1]); + } + } + } + } +} diff --git a/app/Classes/Modules/Open1688/ControllersLogic/GetProductDetailLogic.php b/app/Classes/Modules/Open1688/ControllersLogic/GetProductDetailLogic.php new file mode 100644 index 00000000..1ec60540 --- /dev/null +++ b/app/Classes/Modules/Open1688/ControllersLogic/GetProductDetailLogic.php @@ -0,0 +1,84 @@ + 'Get product detail', + 'message' => 'You have successfully get 1688 product detail' + ]; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws ErrorException + */ + public function logic(Request $request) : JsonResponse + { + $result = Open1688Helper::productDetail($request->route('offer_id')); + $productAttribute = []; + $variants = []; + $uniqueVariants = []; + $variantInfo = []; + $priceList = []; + $variantKeyCombinationOrder = []; + + foreach ($result['productAttribute'] as $attr) { + $productAttribute[$attr['attributeName']] = array_key_exists($attr['attributeName'], $productAttribute) ? $productAttribute[$attr['attributeName']] . ", " . $attr['value'] : $attr['value']; + } + + $result['productAttribute'] = $productAttribute; + + foreach ($result['productSkuInfos'] as $sku) { + $uniqueVariantKey = ''; + foreach ($sku['skuAttributes'] as $skuAttr) { + if (count($variantKeyCombinationOrder) < count($sku['skuAttributes'])) { + array_push($variantKeyCombinationOrder, $skuAttr['attributeName']); + } + if (!in_array($skuAttr['value'], $uniqueVariants)) { + $variants[$skuAttr['attributeName']][] = [ + 'image' => isset($skuAttr['skuImageUrl']) ? $skuAttr['skuImageUrl'] : null, + 'value' => $skuAttr['value'] + ]; + } + + array_push($uniqueVariants, $skuAttr['value']); + + $uniqueVariantKey .= $skuAttr['value']; + } + + $price = isset($sku['price']) ? $sku['price'] : $sku['consignPrice']; + + $variantInfo[$uniqueVariantKey] = [ + 'skuId' => $sku['skuId'], + 'amountOnSale' => $sku['amountOnSale'], + 'price' => $price, + ]; + array_push($priceList, $price); + } + + $result['variants'] = $variants; + $result['variantInfo'] = $variantInfo; + + $minPrice = min($priceList); + $maxPrice = max($priceList); + + $result['priceRange'] = $minPrice === $maxPrice ? $minPrice : "CNY ¥$minPrice - CNY ¥$maxPrice"; + $result['variantKeyCombinationOrder'] = $variantKeyCombinationOrder; + + return $this->response(['data' => $result]); + } +} diff --git a/app/Classes/Modules/Open1688/ControllersLogic/KeywordSearchProductLogic.php b/app/Classes/Modules/Open1688/ControllersLogic/KeywordSearchProductLogic.php new file mode 100644 index 00000000..526c3b1f --- /dev/null +++ b/app/Classes/Modules/Open1688/ControllersLogic/KeywordSearchProductLogic.php @@ -0,0 +1,36 @@ + 'Search 1688 Products', + 'message' => 'You have successfully retrieved a list of products from 1688' + ]; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws ErrorException + */ + public function logic(Request $request) : JsonResponse + { + $result = Open1688Helper::productSearchKeyword($request->input('keyword'), $request->input('page')); + + return $this->response($result); + } +} diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreatePurchaseOrderTransactionLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreatePurchaseOrderTransactionLogic.php index 9bab107f..68072a6e 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/CreatePurchaseOrderTransactionLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreatePurchaseOrderTransactionLogic.php @@ -72,14 +72,32 @@ class CreatePurchaseOrderTransactionLogic extends AbstractControllerLogic $billNumber = $this->generatesTransactionBillNumber->execute('PO-'); - $total = collect($request->input('products'))->sum(function($product){ + $products = $request->input('products'); + + if ($request->input('pushToExisting')) { + $transaction = $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first(); + + if ($transaction) { + foreach ($transaction->transactionDetails as $detail) { + array_push($products, [ + 'stockCode' => $detail->product_code, + 'description' => $detail->product_name, + 'quantity' => $detail->quantity, + 'unit_price' => $detail->price, + 'total' => $detail->amount + ]); + } + } + } + + $total = collect($products)->sum(function($product){ return $product['quantity'] * floatval(str_replace(',', '', $product['unit_price'])); }); $object = new TransactionObject($billNumber, TransactionType::PURCHASE_ORDER, $booking->company->id, 1, 1, PaymentMethodType::CASH, $total, $total, $booking->fix_currency_id, $booking->fix_currency_id, - 1, 0, 0, null, ApprovalStatus::PENDING_SUBMISSION, $request->input('products')); + 1, 0, 0, null, ApprovalStatus::PENDING_SUBMISSION, $products); $transaction = $this->createPurchaseOrderTransactionProcessor->execute($booking, $object); diff --git a/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupLogic.php index f29db055..8e16233b 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupLogic.php @@ -16,10 +16,12 @@ use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; use App\Classes\Modules\Transactions\Services\FetchesGroup; use App\Classes\Modules\Transactions\Services\UpdatesTransaction; use App\Classes\Modules\Transactions\Services\CalculatesTransactionTransferFee; +use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber; use App\Classes\ValueObjects\Constants\TransactionType; use App\Classes\ValueObjects\Constants\PaymentMethodType; use App\Classes\ValueObjects\Constants\SegmentConstants; use App\Classes\ValueObjects\Constants\ApprovalStatus; +use App\Models\Transaction; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use ErrorException; @@ -60,6 +62,9 @@ class UpdateGroupLogic extends AbstractControllerLogic /** @var CreatesFiles */ private $createsFile; + /** @var GeneratesTransactionBillNumber */ + private $generatesTransactionBillNumber; + /** * UpdateGroupLogic constructor. * @param FetchesGroup $fetchesGroup @@ -69,8 +74,9 @@ class UpdateGroupLogic extends AbstractControllerLogic * @param CalculatesTransactionTransferFee $calculatesTransactionTransferFee * @param CreatesDocument $createsDocument * @param CreatesFiles $createsFile + * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber */ - public function __construct(FetchesGroup $fetchesGroup, FetchesCompany $fetchesCompany, CalculatesTransactionServiceCharge $calculatesTransactionServiceCharge, UpdatesTransaction $updatesTransaction, CalculatesTransactionTransferFee $calculatesTransactionTransferFee, CreatesDocument $createsDocument, CreatesFiles $createsFile) + public function __construct(FetchesGroup $fetchesGroup, FetchesCompany $fetchesCompany, CalculatesTransactionServiceCharge $calculatesTransactionServiceCharge, UpdatesTransaction $updatesTransaction, CalculatesTransactionTransferFee $calculatesTransactionTransferFee, CreatesDocument $createsDocument, CreatesFiles $createsFile, GeneratesTransactionBillNumber $generatesTransactionBillNumber) { $this->fetchesGroup = $fetchesGroup; $this->fetchesCompany = $fetchesCompany; @@ -79,6 +85,7 @@ class UpdateGroupLogic extends AbstractControllerLogic $this->calculatesTransactionTransferFee = $calculatesTransactionTransferFee; $this->createsDocument = $createsDocument; $this->createsFile = $createsFile; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; } /** @@ -162,8 +169,61 @@ class UpdateGroupLogic extends AbstractControllerLogic $this->updatesTransaction->execute($transferTransaction, $object); } + // group transfer fee from supplier currency order dashboard manual input + if ($request->input('group_transfer_fee')) { + $fee = $request->input('group_transfer_fee'); + + $group_transfer_fee = $group->morphTransactions()->where('type', TransactionType::TRANSFER_FEE)->first(); + + if ($group_transfer_fee) { + $group_transfer_fee->amount = $fee; + $group_transfer_fee->original_amount = $fee; + $group_transfer_fee->save(); + } else { + $transferFeeNumber = $this->generatesTransactionBillNumber->execute('TRFR-'); + $object = new TransactionObject($transferFeeNumber, TransactionType::TRANSFER_FEE, 1, $supplier->id, + $supplier->banks()->where('default', true)->first()->id, PaymentMethodType::CASH, + $fee, $fee, $group->original_currency_id, $group->original_currency_id, + 1, 0, 0, null, ApprovalStatus::APPROVED); + + $model = new Transaction(); + $model->bill_no = $object->getBillNo(); + $model->type = $object->getTransactionType(); + $model->issuer = $object->getIssuer(); + $model->receiver = $object->getReceiver(); + $model->recipient_bank_account_id = $object->getRecipientBankAccountId(); + $model->payment_method = $object->getPaymentMethod(); + $model->amount = $object->getAmount(); + $model->original_amount = $object->getOriginalAmount(); + $model->currency_id = $object->getCurrencyId(); + $model->original_currency_id = $object->getOriginalCurrencyId(); + $model->currency_rate = $object->getCurrencyRate(); + $model->tax = $object->getTax(); + $model->service_charge = $object->getServiceCharge(); + $model->expires_on = $object->getExpiresOn(); + $model->status = $object->getStatus(); + $model->payment_reference = $object->getPaymentReference(); + + $group->morphTransactions()->save($model); + } + } + + $group_transfer_fee = $group->morphTransactions()->where('type', TransactionType::TRANSFER_FEE)->first(); + + $group_transfer_fee_original_amount = 0; + + if ($group_transfer_fee) { + $group_transfer_fee_original_amount = $group_transfer_fee->original_amount; + } + + $transferFeeTransactions = $group->transactions()->with([ + 'transactions' => function ($transaction) { + return $transaction->where('type', TransactionType::TRANSFER_FEE); + }])->get()->pluck('transactions')->flatten(); + $group->issuer = $supplier->id; - $group->amount = $group->transactions()->sum('amount'); + $group->original_amount = $group->transactions()->sum('original_amount') + ((float)$transferFeeTransactions->sum('service_charge') + (float)$group_transfer_fee_original_amount); + $group->amount = $group->transactions()->sum('amount') + (((float)$transferFeeTransactions->sum('service_charge') + (float)$group_transfer_fee_original_amount) / $rate); $group->currency_rate = $rate; $group->tax = $group->transactions()->sum('tax'); $group->service_charge = $group->transactions()->sum('service_charge'); @@ -172,12 +232,7 @@ class UpdateGroupLogic extends AbstractControllerLogic $group->documents()->delete(); - $transferFeeTransactions = $group->transactions()->with([ - 'transactions' => function ($transaction) { - return $transaction->where('type', TransactionType::TRANSFER_FEE); - }])->get()->pluck('transactions')->flatten(); - - $pdf = LaravelMpdf::loadView('pages.pdfs.currency_vendor_order', ['transactions' => $group->transactions, 'transferFeeTransactions' => $transferFeeTransactions, 'supplier' => $supplier]); + $pdf = LaravelMpdf::loadView('pages.pdfs.currency_vendor_order', ['transactions' => $group->transactions, 'transferFeeTransactions' => $transferFeeTransactions, 'supplier' => $supplier, 'groupTransferFeeOriginalAmount' => $group_transfer_fee_original_amount]); $object = new DocumentObject( DocumentType::CURRENCY_VENDOR_ORDER, diff --git a/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php index 7f105dc8..76f7cef7 100644 --- a/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php +++ b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php @@ -14,13 +14,16 @@ use App\Classes\Modules\Bookings\Services\CalculatesBookingCurrencyAverageRate; use App\Classes\Modules\Companies\Services\FetchesCompany; use App\Classes\Modules\Bookings\Services\UpdatesBookingStatus; use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; +use App\Classes\Jobs\CreateMilestoneRewardByTransactionJob; use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\SegmentConstants; use App\Classes\ValueObjects\Constants\TransactionType; use App\Classes\ValueObjects\Constants\DocumentType; +use App\Classes\ValueObjects\Constants\Milestones; use App\Models\Booking; use App\Models\SegmentConstant; + class CreateInvoiceTransactionProcessor { @@ -123,6 +126,7 @@ class CreateInvoiceTransactionProcessor $transaction = $booking->transactions() ->where('type', TransactionType::PAYMENT) ->latest()->get()[0]; + CreateMilestoneRewardByTransactionJob::dispatch($transaction, [Milestones::MILESTONE_1]); $billNumber = $this->generatesTransactionBillNumber->execute('INV-'); diff --git a/app/Classes/ValueObjects/Constants/MilestoneCreationOptions.php b/app/Classes/ValueObjects/Constants/MilestoneCreationOptions.php index 4631b25b..6e94e610 100644 --- a/app/Classes/ValueObjects/Constants/MilestoneCreationOptions.php +++ b/app/Classes/ValueObjects/Constants/MilestoneCreationOptions.php @@ -6,8 +6,9 @@ class MilestoneCreationOptions { const OPTIONS_MILESTONE_NAME= [ ['text' => 'MILESTONE 1', 'id' => Milestones::MILESTONE_1], - ['text' => 'MILESTONE 2', 'id' => Milestones::MILESTONE_2], - ['text' => 'MILESTONE 3', 'id' => Milestones::MILESTONE_3], + // ['text' => 'MILESTONE DEMO 1', 'id' => Milestones::MILESTONE_DEMO_1], + // ['text' => 'MILESTONE 2', 'id' => Milestones::MILESTONE_2], + // ['text' => 'MILESTONE 3', 'id' => Milestones::MILESTONE_3], // ['text' => 'MILESTONE 4', 'id' => Milestones::MILESTONE_4], // ['text' => 'MILESTONE 5', 'id' => Milestones::MILESTONE_5], // ['text' => 'MILESTONE 6', 'id' => Milestones::MILESTONE_6], diff --git a/app/Classes/ValueObjects/Constants/Milestones.php b/app/Classes/ValueObjects/Constants/Milestones.php index 19961d68..6a85abbe 100644 --- a/app/Classes/ValueObjects/Constants/Milestones.php +++ b/app/Classes/ValueObjects/Constants/Milestones.php @@ -4,9 +4,10 @@ namespace App\Classes\ValueObjects\Constants; class Milestones { - public const MILESTONE_1 = 'MILESTONE 1'; //Authentication (Sign in) or CreateCustomerLogic (Sign up) - public const MILESTONE_2 = 'MILESTONE 2'; //Create Identification Document - public const MILESTONE_3 = 'MILESTONE 3'; //Assign Company to Segment Logic -segment.assign when accept 1688 + public const MILESTONE_1 = 'MILESTONE 1'; //Has 2 successful bookings + // public const MILESTONE_DEMO_1 = 'MILESTONE_DEMO_1 1'; //Authentication (Sign in) or CreateCustomerLogic (Sign up) + // public const MILESTONE_2 = 'MILESTONE 2'; //Create Identification Document + // public const MILESTONE_3 = 'MILESTONE 3'; //Assign Company to Segment Logic -segment.assign when accept 1688 // public const MILESTONE_4 = 'MILESTONE 4'; //Create Bank Logic (Transfer Now from dashboard) // public const MILESTONE_5 = 'MILESTONE 5'; //Create Booking Logic // public const MILESTONE_6 = 'MILESTONE 6'; //Create Address Logic (At transfer page before create booking) diff --git a/app/Console/Commands/UpdateBillGroupAndGroupToIncludeTransferFee.php b/app/Console/Commands/UpdateBillGroupAndGroupToIncludeTransferFee.php new file mode 100644 index 00000000..72a1c8f2 --- /dev/null +++ b/app/Console/Commands/UpdateBillGroupAndGroupToIncludeTransferFee.php @@ -0,0 +1,130 @@ +updateGroupLogic = $updateGroupLogic; + } + + /** + * Execute the console command. + * + * @return int + */ + public function handle() + { + + // update group to include transfer fee + $groups = Group::all(); + + foreach ($groups as $group) { + $originalTransferFees = (float)Transaction::where('type', TransactionType::TRANSFER_FEE)->whereIn('owner_id', $group->transactions->pluck('id'))->sum('service_charge'); + $correctOriginalAmount = $group->transactions()->sum('original_amount'); + $correctOriginalAmount += $originalTransferFees; + $correctAmount = $group->transactions()->sum('amount'); + $transferFees = $originalTransferFees / $group->currency_rate; + $correctAmount += $transferFees; + + if ($group->original_amount != $correctOriginalAmount || $group->amount != $correctAmount) { + $group->original_amount = $correctOriginalAmount; + $group->amount = $correctAmount; + $group->save(); + + $this->info("updated group id: {$group->id}, added transfer fee CNY {$correctOriginalAmount}"); + } + } + + // update group calculation to include individual group transfer fee + $groups = Group::whereHas('morphTransactions', function ($q) { + $q->where('type', TransactionType::TRANSFER_FEE); + })->get(); + + foreach ($groups as $group) { + $route = FacadesRoute::getRoutes()->getByName('api.transaction.group.update'); + $request = Request::create(route('api.transaction.group.update', $group->id)); + $uri = $route->uri; + $request->setRouteResolver(function () use ($request, $uri) { + // Associate Route to request so we can access route parameters. + return (new Route('PUT', $uri, []))->bind($request); + }); + + $request['rate'] = $group->currency_rate; + $request['supplier_id'] = $group->issuer; + $this->updateGroupLogic->execute($request); + + $group_transfer_fee = $group->morphTransactions()->where('type', TransactionType::TRANSFER_FEE)->first(); + $this->info("updated group id: {$group->id}, added transfer fee to individual white form CNY {$group_transfer_fee->original_amount}"); + } + + // update bill group calculation to include individual group transfer fee + $billGroups = BillGroup::all(); + + foreach ($billGroups as $billGroup) { + // ignore those has bill group refund + if ($billGroup->billRefunds()->count() > 0) { + continue; + } + + $totalOriginal = $billGroup->groups()->sum('original_amount'); + $total = $billGroup->groups()->sum('amount'); + + // update bill group payment transaction amount if there is only 1 payment transaction + $payment_transactions = $billGroup->transactions()->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->get(); + + if ($payment_transactions->count() === 1) { + $payment_transaction = $payment_transactions->first(); + if ($payment_transaction->amount === $billGroup->amount) { + $payment_transaction->original_amount = $total; + $payment_transaction->amount = $total; + $payment_transaction->save(); + $this->info("updated bill group payment transaction id: {$payment_transaction->id}, update original amount to CNY {$totalOriginal}"); + } + } + + // update bill group amount and original amount + $billGroup->original_amount = $totalOriginal; + $billGroup->amount = $total; + $billGroup->save(); + + $this->info("updated bill group id: {$billGroup->id}, added transfer fee, final original amount is CNY {$totalOriginal}"); + } + } +} diff --git a/app/Console/Commands/UpdateGroupWithTransferFee.php b/app/Console/Commands/UpdateGroupWithTransferFee.php deleted file mode 100644 index dec74d5c..00000000 --- a/app/Console/Commands/UpdateGroupWithTransferFee.php +++ /dev/null @@ -1,68 +0,0 @@ -get(); - - foreach ($groups as $group) { - $originalTransferFees = (float)Transaction::where('type', TransactionType::TRANSFER_FEE)->whereIn('owner_id', $group->transactions->pluck('id'))->sum('service_charge'); - $correctOriginalAmount = $group->transactions()->sum('original_amount'); - $correctOriginalAmount += $originalTransferFees; - $correctAmount = $group->transactions()->sum('amount'); - $transferFees = $originalTransferFees / $group->currency_rate; - $correctAmount += $transferFees; - - if ($group->original_amount != $correctOriginalAmount) { - $group->original_amount = $correctOriginalAmount; - $group->amount = $correctAmount; - $group->save(); - } - } - } -} diff --git a/app/Http/Controllers/Open1688/Open1688Controller.php b/app/Http/Controllers/Open1688/Open1688Controller.php new file mode 100644 index 00000000..2ed20540 --- /dev/null +++ b/app/Http/Controllers/Open1688/Open1688Controller.php @@ -0,0 +1,30 @@ +execute($request); + } + + /** + * @param Request $request + * @param GetProductDetailLogic $logic + * @return JsonResponse + */ + public function getProductDetail(Request $request, GetProductDetailLogic $logic): JsonResponse { + return $logic->execute($request); + } + +} diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 20741c52..42e1a43e 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -47,12 +47,14 @@ class Kernel extends HttpKernel VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, // \App\Http\Middleware\WebRouteLogs::class, + \App\Http\Middleware\WebResponseTimeLog::class, ], 'api' => [ 'throttle:300,1', \Illuminate\Routing\Middleware\SubstituteBindings::class, // \App\Http\Middleware\ApiRouteLogs::class, + \App\Http\Middleware\ApiResponseTimeLog::class, ], 'apipub' => [ diff --git a/app/Http/Middleware/ApiResponseTimeLog.php b/app/Http/Middleware/ApiResponseTimeLog.php new file mode 100644 index 00000000..aae6d91e --- /dev/null +++ b/app/Http/Middleware/ApiResponseTimeLog.php @@ -0,0 +1,29 @@ +route(); + $routeName = $route ? $route->getName() : 'undefined'; + $uri = $request->getPathInfo(); + + $startTime = microtime(true); // Start time + + $response = $next($request); // Handle the request + + $endTime = microtime(true); // End time + $responseTime = $endTime - $startTime; // Calculate the response time + + Log::channel('apiResponseTimeLog')->info("\nRequest to route: {$uri} \nRoute name: {$routeName} \nTime Taken: " . number_format($responseTime * 1000, 2) . "ms\n"); + + return $response; + } +} diff --git a/app/Http/Middleware/WebResponseTimeLog.php b/app/Http/Middleware/WebResponseTimeLog.php new file mode 100644 index 00000000..9a4c3e6e --- /dev/null +++ b/app/Http/Middleware/WebResponseTimeLog.php @@ -0,0 +1,29 @@ +route(); + $routeName = $route ? $route->getName() : 'undefined'; + $uri = $request->getPathInfo(); + + $startTime = microtime(true); // Start time + + $response = $next($request); // Handle the request + + $endTime = microtime(true); // End time + $responseTime = $endTime - $startTime; // Calculate the response time + + Log::channel('webResponseTimeLog')->info("\nRequest to route: {$uri} \nRoute name: {$routeName} \nTime Taken: " . number_format($responseTime * 1000, 2) . "ms\n"); + + return $response; + } +} diff --git a/app/Http/Resources/TransactionDetailResource.php b/app/Http/Resources/TransactionDetailResource.php index 4257a9fb..63c6661b 100644 --- a/app/Http/Resources/TransactionDetailResource.php +++ b/app/Http/Resources/TransactionDetailResource.php @@ -14,14 +14,23 @@ class TransactionDetailResource extends JsonResource */ public function toArray($request) { - + $item_from_1688 = str_contains($this->product_code, 'offerId'); + $offer_id_1688 = null; + if ($item_from_1688) { + $offerId = explode(',', $this->product_code)[0]; + $offer_id_1688 = substr($offerId, strpos($offerId, ':') + 1); + } + + return [ 'id' => $this->id, 'stockCode' => $this->product_code, 'description' => $this->product_name, 'quantity' => $this->quantity, 'unit_price' => (double) $this->price, - 'total' => (double) $this->amount + 'total' => (double) $this->amount, + 'item_from_1688' => $item_from_1688, + 'offer_id_1688' => $offer_id_1688 ]; } } diff --git a/app/Http/Resources/VoucherResource.php b/app/Http/Resources/VoucherResource.php index 3f3112bb..031cf39f 100644 --- a/app/Http/Resources/VoucherResource.php +++ b/app/Http/Resources/VoucherResource.php @@ -16,7 +16,7 @@ class VoucherResource extends JsonResource public function toArray($request) { $filteredRedemptions = new ArrayObject([]); - if ($request->has('filters') && str_contains($request->input('filters'), "has_active_reward")) { + if ($request->has('filters') && str_contains($request->input('filters'), "has_vouchers_all")) { $filteredRedemptions = new ArrayObject([]); } else{ diff --git a/app/Models/StatementTransaction.php b/app/Models/StatementTransaction.php index 4bba7903..6f9013b7 100644 --- a/app/Models/StatementTransaction.php +++ b/app/Models/StatementTransaction.php @@ -56,7 +56,9 @@ class StatementTransaction extends Model public function scopeDoesntMapStatement($query) { - $query->whereDoesntHave('owners', function($query){ + $query->whereHas('account', function($query) { + $query->where('statement_accounts.number', 568603010762); + })->whereDoesntHave('owners', function($query){ return $query->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); })->orderBy('posting_date'); } diff --git a/config/logging.php b/config/logging.php index 0c9a6ec1..3d2c5ac9 100644 --- a/config/logging.php +++ b/config/logging.php @@ -112,6 +112,22 @@ return [ 'level' => 'info', ], + 'apiResponseTimeLog' => [ + 'driver' => 'single', + 'path' => storage_path('logs/apiResponseTime.log'), + 'level' => 'info', + ], + + 'webResponseTimeLog' => [ + 'driver' => 'single', + 'path' => storage_path('logs/webResponseTimeLog.log'), + 'level' => 'info', + ], + 'guzzleShippingPortal' => [ + 'driver' => 'errorlog', + 'level' => 'debug', + ], + 'vue_polling' => [ 'driver' => 'single', 'path' => storage_path('logs/laravel_vue_plling.log'), diff --git a/config/open1688.php b/config/open1688.php new file mode 100644 index 00000000..7cf948f4 --- /dev/null +++ b/config/open1688.php @@ -0,0 +1,11 @@ + env('OPEN_1688_APP_KEY', ''), + 'app_secret' => env('OPEN_1688_APP_SECRET', ''), + 'access_token' => env('open_1688_ACCESS_TOKEN', ''), + 'refresh_token' => env('open_1688_REFRESH_TOKEN', ''), + 'url' => env('OPEN_1688_URL', ''), + 'product_search_keyword_api' => env('OPEN_1688_PRODUCT_SEARCH_KEYWORD', ''), + 'product_detail_api' => env('OPEN_1688_PRODUCT_DETAIL', ''), +]; diff --git a/database/migrations/2022_12_27_165842_create_route_logs_table.php b/database/migrations/2022_12_27_165842_create_route_logs_table.php index bdab0257..78b18b2a 100644 --- a/database/migrations/2022_12_27_165842_create_route_logs_table.php +++ b/database/migrations/2022_12_27_165842_create_route_logs_table.php @@ -13,21 +13,21 @@ class CreateRouteLogsTable extends Migration */ public function up() { - Schema::create('route_logs', function (Blueprint $table) { - $table->id(); - $table->foreignId('user_id')->unsigned(); - $table->string('ip_address'); - $table->string('url', 255); - $table->string('request_method'); - $table->string('browser')->nullable(); - $table->string('platform')->nullable(); - $table->string('longitude')->nullable(); - $table->string('latitude')->nullable(); - $table->string('last_page')->nullable(); - $table->string('countryname')->nullable(); - $table->integer('route_type'); - $table->timestamps(); - }); + // Schema::create('route_logs', function (Blueprint $table) { + // $table->id(); + // $table->foreignId('user_id')->unsigned(); + // $table->string('ip_address'); + // $table->string('url', 255); + // $table->string('request_method'); + // $table->string('browser')->nullable(); + // $table->string('platform')->nullable(); + // $table->string('longitude')->nullable(); + // $table->string('latitude')->nullable(); + // $table->string('last_page')->nullable(); + // $table->string('countryname')->nullable(); + // $table->integer('route_type'); + // $table->timestamps(); + // }); } /** diff --git a/database/migrations/2023_12_18_230408_create_index_for_transaction_table.php b/database/migrations/2023_12_18_230408_create_index_for_transaction_table.php new file mode 100644 index 00000000..e343589f --- /dev/null +++ b/database/migrations/2023_12_18_230408_create_index_for_transaction_table.php @@ -0,0 +1,58 @@ +index('status'); + $table->index('type'); + $table->index('payment_method'); + $table->index('payment_reference'); + $table->index('bill_no'); + $table->index('owner_type'); + $table->index('owner_id'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('transactions', function (Blueprint $table) { + $table->dropIndex('owner_type'); + $table->dropIndex('owner_id'); + $table->dropIndex('type'); + $table->dropIndex('issuer'); + $table->dropIndex('receiver'); + $table->dropIndex('recipient_bank_account_id'); + $table->dropIndex('payment_method'); + $table->dropIndex('payment_reference'); + $table->dropIndex('bill_no'); + $table->dropIndex('amount'); + $table->dropIndex('original_amount'); + $table->dropIndex('currency_id'); + $table->dropIndex('original_currency_id'); + $table->dropIndex('currency_rate'); + $table->dropIndex('tax'); + $table->dropIndex('service_charge'); + $table->dropIndex('expires_on'); + $table->dropIndex('status'); + $table->dropIndex('deleted_at'); + $table->dropIndex('created_at'); + $table->dropIndex('updated_at'); + }); + } +} diff --git a/package.json b/package.json index 6b27498c..32058424 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,8 @@ "vue": "^2.7.14", "vue-avatar": "^2.1.8", "vue-debounce": "^2.6.0", - "vue-template-compiler": "^2.7.14", + "vue-gtag": "^1.16.1", + "vue-template-compiler": "^2.6.10", "vue-the-mask": "^0.11.1", "vuelidate": "^0.7.4", "vuex": "^3.1.1" diff --git a/resources/assets/vue/app.js b/resources/assets/vue/app.js index 19d403c5..11d3ed9f 100644 --- a/resources/assets/vue/app.js +++ b/resources/assets/vue/app.js @@ -2,6 +2,7 @@ /** Dependencies */ import Vue from 'vue' import store from './vuex/store'; +import VueGtag from 'vue-gtag' window.route = require('./general/functions/router'); @@ -59,6 +60,18 @@ Vue.component(Avatar); const files = require.context('./', true, /\.vue$/i); files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default)); +// Google Analytics 4 (GA4) Integration +Vue.use(VueGtag, { + property: { + id: 'G-FEJNZTR0WP', + params: { + user_id: store.getters.getUserId + } + } +}); + +console.log('Google Tag pushed'); + const app = new Vue({ el: '#app', store, diff --git a/resources/assets/vue/components/accounting/elements/EditSingleItemInListComponent.vue b/resources/assets/vue/components/accounting/elements/EditSingleItemInListComponent.vue index 5d1341b1..3e077bbc 100644 --- a/resources/assets/vue/components/accounting/elements/EditSingleItemInListComponent.vue +++ b/resources/assets/vue/components/accounting/elements/EditSingleItemInListComponent.vue @@ -136,7 +136,7 @@ case 'Sales': return ['Exchange', 'Izyim', 'Lite', 'Cntr', 'Probashi', 'Pets']; case 'Top Up': - return ['Exchange', 'Izyim']; + return ['Exchange', 'Izyim', 'Lite']; default: return []; } diff --git a/resources/assets/vue/components/accounting/elements/StatementTransactionComponent.vue b/resources/assets/vue/components/accounting/elements/StatementTransactionComponent.vue index 787f2f37..d1b59663 100644 --- a/resources/assets/vue/components/accounting/elements/StatementTransactionComponent.vue +++ b/resources/assets/vue/components/accounting/elements/StatementTransactionComponent.vue @@ -10,7 +10,8 @@
RM{{ item.voucher.value/100 }} Discount
{{ item.voucher.value }}% Discount
The recipient can expect to receive the transfer within 1-3 working days. Explore our BANK TRANSFER (SAVER) option for a better rate!
-Enjoy a better rate with this option! The recipient will receive the transfer after 3-5 working days..
+The recipient can expect to receive the transfer within 3-5 working days. Explore our BANK TRANSFER (SAVER) option for a better rate!
+Enjoy a better rate with this option! The recipient will receive the transfer after 5-7 working days..

Nothing To Show Here
+Voucher claimed
++ This voucher has expired. +
Valid till {{ item.voucher.end_date }}
- - + Non-expired