Merge branch 'dillon/110-period-lock-c' into vapor/development

This commit is contained in:
Dillon Ngo
2026-01-27 11:52:41 +08:00
73 changed files with 9075 additions and 277 deletions
@@ -2,9 +2,9 @@
namespace App\Classes\Jobs\Commands\V2;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\Settings\Services\CreatesKeyValuePair;
use App\Classes\Modules\Settings\Services\UpdatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\KeyValuePairs\Services\CreatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\UpdatesKeyValuePair;
use App\Classes\Modules\Bookings\Processors\RegenerateInvoiceBookingProcessor;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\KVPKey;
@@ -2,9 +2,9 @@
namespace App\Classes\Jobs\Commands\V2;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\Settings\Services\CreatesKeyValuePair;
use App\Classes\Modules\Settings\Services\UpdatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\KeyValuePairs\Services\CreatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\UpdatesKeyValuePair;
use App\Classes\ValueObjects\Constants\KVPKey;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
@@ -2,9 +2,9 @@
namespace App\Classes\Jobs\Commands\V2;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\Accounts\Services\CreatesKeyValuePair;
use App\Classes\Modules\Accounts\Services\UpdatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\KeyValuePairs\Services\CreatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\UpdatesKeyValuePair;
use App\Classes\ValueObjects\Constants\KVPKey;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
@@ -2,9 +2,9 @@
namespace App\Classes\Jobs\Commands\V2;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\Accounts\Services\CreatesKeyValuePair;
use App\Classes\Modules\Accounts\Services\UpdatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\KeyValuePairs\Services\CreatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\UpdatesKeyValuePair;
use App\Classes\ValueObjects\Constants\KVPKey;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
@@ -2,9 +2,9 @@
namespace App\Classes\Jobs\Commands\V2;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\Settings\Services\CreatesKeyValuePair;
use App\Classes\Modules\Settings\Services\UpdatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\KeyValuePairs\Services\CreatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\UpdatesKeyValuePair;
use App\Classes\ValueObjects\Constants\KVPKey;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
+2 -2
View File
@@ -2,8 +2,8 @@
namespace App\Classes\Jobs;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\Settings\Services\CreatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\KeyValuePairs\Services\CreatesKeyValuePair;
use App\Classes\Notifications\WelcomeVoucherEmail;
use App\Models\User;
use App\Models\Voucher;
@@ -183,8 +183,10 @@ class CreateCustomerLogic extends AbstractControllerLogic
}
}
// Track affiliate registration if user came from affiliate link
$this->tracksAffiliateRegistration->execute($user, $request->get('tracking'));
// Track affiliate registration if user came from affiliate link.
// Prefer ?tracking= from request; fallback to cookie set by TrackAffiliateClick on /signup visit.
$code = $request->get('tracking') ?? $request->cookie(\App\Classes\Modules\Affiliate\Services\TracksAffiliateClick::COOKIE_NAME);
$this->tracksAffiliateRegistration->execute($user, $code);
return $this->response($this->authenticationProcessor->execute($request, false));
@@ -61,8 +61,8 @@ class CreateSystemUserLogic extends AbstractControllerLogic
$this->canCreateUser->passes($user_object);
$user = $this->createsUser->execute($user_object);
$token = $user->createToken('my-app-token', ['*'])->plainTextToken;
return $this->response(['token' => $token]);
// $token = $user->createToken('my-app-token', ['*'])->plainTextToken;
// return $this->response(['token' => $token]);
}
return $this->response([]);
}
@@ -2,33 +2,58 @@
namespace App\Classes\Modules\Affiliate\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Affiliate\Services\CreatesAffiliate;
use App\Classes\Modules\Affiliate\DataTransferObjects\AffiliateObject;
use App\Classes\Modules\Affiliate\Standards\Rules\CanCreateAffiliate;
use App\Http\Resources\AffiliateResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class CreateAffiliateLogic
class CreateAffiliateLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification(): array
{
return [
'title' => 'Created Affiliate',
'message' => 'You have successfully created a new Affiliate Code'
];
}
/** @var CanCreateAffiliate */
private $canCreateAffiliate;
/** @var CreatesAffiliate */
private $createsAffiliate;
/**
* CreateAffiliateLogic constructor.
* @param CanCreateAffiliate $canCreateAffiliate
* @param CreatesAffiliate $createsAffiliate
*/
public function __construct(CreatesAffiliate $createsAffiliate)
public function __construct(
CanCreateAffiliate $canCreateAffiliate,
CreatesAffiliate $createsAffiliate
)
{
$this->canCreateAffiliate = $canCreateAffiliate;
$this->createsAffiliate = $createsAffiliate;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function execute(Request $request): JsonResponse
public function logic(Request $request): JsonResponse
{
$code = $request->input('code');
$code = $code !== null ? (string) $code : '';
$isActive = $request->input('is_active', true);
// Convert string 'true'/'false' to boolean if needed
if (is_string($isActive)) {
@@ -43,12 +68,13 @@ class CreateAffiliateLogic
$isActive
);
// Validate the affiliate object
$this->canCreateAffiliate->passes($object);
// Create the affiliate
$affiliate = $this->createsAffiliate->execute($object);
return response()->json([
'message' => 'Affiliate code created successfully',
'data' => $affiliate
]);
return $this->resourceResponse(new AffiliateResource($affiliate));
}
}
@@ -18,23 +18,17 @@ class CreatesAffiliate extends AbstractUpdateRecord
public function execute(AffiliateObject $object)
{
$code = $object->getCode();
// Auto-generate code if not provided
if (empty($code)) {
$code = $this->generateUniqueCode();
} else {
// Validate uniqueness of user-provided code (including soft-deleted records)
$existingAffiliate = Affiliate::where('code', $code)
->whereNull('deleted_at')
->first();
if ($existingAffiliate) {
throw new \App\Classes\Exceptions\MalformedRequestException('Affiliate code already exists. Please choose a different code.');
}
// Uppercase the code for consistency
$code = strtoupper($code);
}
$model = new Affiliate();
$model->code = $code;
$model->code = strtoupper($code);
$model->campaign_name = $object->getCampaignName();
$model->campaign_description = $object->getCampaignDescription();
$model->is_active = $object->getIsActive();
@@ -48,19 +42,19 @@ class CreatesAffiliate extends AbstractUpdateRecord
/**
* Generate a unique affiliate code
*
*
* @return string
*/
private function generateUniqueCode(): string
{
$maxAttempts = 10;
$attempts = 0;
do {
// Increased from 12 to 16 characters for better uniqueness
$code = Str::random(16);
$attempts++;
if ($attempts >= $maxAttempts) {
// Fallback to UUID if we can't generate unique code
$code = strtoupper(Str::substr(str_replace('-', '', Str::uuid()), 0, 16));
@@ -12,7 +12,7 @@ class TracksAffiliateOrder
{
/**
* Track when a user with an affiliate code creates an order
*
*
* @param Booking $booking
* @return Affiliate|null
*/
@@ -48,22 +48,22 @@ class TracksAffiliateOrder
// Check if this booking has already been counted
// We'll use a KeyValuePair to track which bookings have been counted
$kvpKey = 'affiliate_order_tracked_' . $affiliate->id;
$existingKvp = $booking->attributesKVP()
->where('key', $kvpKey)
->exists();
if ($existingKvp) {
return $affiliate; // Already counted
}
// Mark this booking as tracked
$keyValuePairObject = new \App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject(
$keyValuePairObject = new \App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject(
$kvpKey,
'1'
);
$createsKeyValuePair = app()->make(\App\Classes\Modules\Accounts\Services\CreatesKeyValuePair::class);
$createsKeyValuePair = app()->make(\App\Classes\Modules\KeyValuePairs\Services\CreatesKeyValuePair::class);
$createsKeyValuePair->execute($booking, $keyValuePairObject);
// Increment orders count atomically
@@ -13,12 +13,14 @@ class TracksAffiliateRegistration
{
/**
* Track when a user registers with an affiliate code
*
*
* @param User $user
* @return Affiliate|null
*/
public function execute(User $user, string $code): ?Affiliate
public function execute(User $user, ?string $code = null): ?Affiliate
{
// Log::info('TracksAffiliateRegistration::execute', ['user' => $user, 'code' => $code]);
if (!$code || !$this->isValidCode($code)) {
Log::info('Code is not valid', ['code' => $code]);
return null;
@@ -65,7 +67,7 @@ class TracksAffiliateRegistration
/**
* Validate affiliate code format
*
*
* @param string $code
* @return bool
*/
@@ -0,0 +1,52 @@
<?php
namespace App\Classes\Modules\Affiliate\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\Affiliate\DataTransferObjects\AffiliateObject;
use App\Classes\Modules\Affiliate\Standards\Validators\AffiliateCreateValidation;
class CanCreateAffiliate extends AbstractRule
{
/** @var AffiliateCreateValidation */
private $affiliateCreateValidation;
/**
* CanCreateAffiliate constructor.
* @param AffiliateCreateValidation $affiliateCreateValidation
*/
public function __construct(AffiliateCreateValidation $affiliateCreateValidation)
{
$this->affiliateCreateValidation = $affiliateCreateValidation;
}
/**
* @param AffiliateObject $object
* @return bool
*/
protected function authorized($object): bool
{
// Authorization is handled by policy in controller
return true;
}
/**
* @param AffiliateObject $object
* @return bool
* @throws \App\Classes\Exceptions\RequestValidationException
*/
protected function validators($object): bool
{
return $this->affiliateCreateValidation->validate($object);
}
/**
* @param AffiliateObject $object
* @return bool
*/
protected function criteria($object): bool
{
// No additional criteria needed for affiliate creation
return true;
}
}
@@ -0,0 +1,69 @@
<?php
namespace App\Classes\Modules\Affiliate\Standards\Validators;
use App\Classes\General\Abstracts\AbstractValidation;
use App\Classes\Modules\Affiliate\DataTransferObjects\AffiliateObject;
use App\Models\Affiliate;
use Illuminate\Validation\Rule;
class AffiliateCreateValidation extends AbstractValidation
{
/**
* @param AffiliateObject $object
* @return array
*/
protected function data($object): array
{
return [
'code' => $object->getCode(),
'campaign_name' => $object->getCampaignName(),
'campaign_description' => $object->getCampaignDescription(),
'is_active' => $object->getIsActive(),
];
}
/**
* @return array
*/
protected function rules(): array
{
return [
'code' => [
'nullable',
'string',
'min:3',
'max:255',
'regex:/^[a-zA-Z0-9_-]+$/',
function ($attribute, $value, $fail) {
if (!empty($value)) {
$uppercaseCode = strtoupper($value);
$exists = Affiliate::whereRaw('UPPER(code) = ?', [$uppercaseCode])
->whereNull('deleted_at')
->exists();
if ($exists) {
$fail('Affiliate code already exists. Please choose a different code.');
}
}
},
],
'campaign_name' => 'required|string|max:255',
'campaign_description' => 'nullable|string|max:65535',
'is_active' => 'required|boolean',
];
}
/**
* @return array
*/
protected function messages(): array
{
return [
'code.regex' => 'The affiliate code may only contain letters, numbers, hyphens, and underscores.',
'code.min' => 'The affiliate code must be at least 3 characters.',
'campaign_name.required' => 'A campaign name is required.',
'campaign_name.max' => 'The campaign name cannot exceed 255 characters.',
];
}
}
@@ -7,8 +7,8 @@ use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Banks\Services\UpdatesBank;
use App\Classes\Modules\Banks\Services\CreatesOrUpdateBank;
use App\Classes\Modules\Banks\DataTransferObjects\BankObject;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\Settings\Services\CreatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\KeyValuePairs\Services\CreatesKeyValuePair;
use Illuminate\Database\Eloquent\Model;
use App\Models\Bank;
@@ -6,7 +6,7 @@ use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Bookings\Standards\Rules\CanCreateBooking;
use App\Classes\Modules\Bookings\Services\FetchesBooking;
use App\Classes\Modules\Settings\Services\CreatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\CreatesKeyValuePair;
use App\Classes\ValueObjects\Constants\KVPKey;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -62,6 +62,8 @@ class CreateBookingLockLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
// cief todo: 110 - CanCreateBookingLock
// $password = $request->input('password');
// if($password !== 'prototype'){
// throw new AccessForbiddenException('Incorrect Password');
@@ -53,6 +53,8 @@ class DeleteBookingLockLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
// cief todo: 110 - CanDeleteBookingLock
$password = $request->input('password');
if($password !== 'prototype'){
throw new AccessForbiddenException('Incorrect Password');
@@ -13,14 +13,14 @@ use App\Classes\Modules\Bookings\Services\FetchesBooking;
use App\Classes\Modules\Bookings\Services\UpdatesBookingInvoiceStatus;
use App\Classes\Modules\Bookings\Services\UpdatesBookingFixedAmount;
use App\Classes\Modules\Bookings\Standards\Rules\CanUpdateBooking;
use App\Classes\Modules\Rules\Services\RuleEvaluator;
use App\Classes\Modules\Rules\Standards\Rules\CanPassTransferPeriodLockRule;
use App\Classes\Modules\Rules\DataTransferObjects\CheckTransferPeriodLockRuleVariant2DTO;
use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionV2Processor;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Http\Resources\BookingResource;
use App\Classes\Modules\Rules\DataTransferObjects\CheckTransferPeriodLockRuleVariant2DTO;
use App\Classes\Modules\Rules\Services\RuleEvaluator;
use App\Classes\Modules\Rules\Standards\Rules\CanPassTransferPeriodLockRule;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -79,8 +79,10 @@ class UpdateBookingAmountLogic extends AbstractControllerLogic
* @param CanPassTransferPeriodLockRule $canPassTransferPeriodLockRule
* @param UpdatesBookingInvoiceStatus $updatesBookingInvoiceStatus
* @param CreateInvoiceTransactionV2Processor $createInvoiceTransactionProcessor
* @param RuleEvaluator $ruleEvaluator
* @param CanPassTransferPeriodLockRule $canPassTransferPeriodLockRule
*/
public function __construct(CanUpdateBooking $canUpdateBooking, UpdatesBookingFixedAmount $updatesBookingFixedAmount, FetchesBooking $fetchesBooking, CalculatesBookingOutstanding $calculatesBookingOutstanding, UpdatesTransactionStatus $updatesTransactionStatus, RuleEvaluator $ruleEvaluator, CanPassTransferPeriodLockRule $canPassTransferPeriodLockRule, UpdatesBookingInvoiceStatus $updatesBookingInvoiceStatus, CreateInvoiceTransactionV2Processor $createInvoiceTransactionProcessor)
public function __construct(CanUpdateBooking $canUpdateBooking, UpdatesBookingFixedAmount $updatesBookingFixedAmount, FetchesBooking $fetchesBooking, CalculatesBookingOutstanding $calculatesBookingOutstanding, UpdatesTransactionStatus $updatesTransactionStatus, UpdatesBookingInvoiceStatus $updatesBookingInvoiceStatus, CreateInvoiceTransactionV2Processor $createInvoiceTransactionProcessor, RuleEvaluator $ruleEvaluator, CanPassTransferPeriodLockRule $canPassTransferPeriodLockRule)
{
$this->canUpdateBooking = $canUpdateBooking;
$this->updatesBookingFixedAmount = $updatesBookingFixedAmount;
@@ -91,6 +93,8 @@ class UpdateBookingAmountLogic extends AbstractControllerLogic
$this->canPassTransferPeriodLockRule = $canPassTransferPeriodLockRule;
$this->updatesBookingInvoiceStatus = $updatesBookingInvoiceStatus;
$this->createInvoiceTransactionProcessor = $createInvoiceTransactionProcessor;
$this->ruleEvaluator = $ruleEvaluator;
$this->canPassTransferPeriodLockRule = $canPassTransferPeriodLockRule;
}
/**
@@ -101,18 +105,18 @@ class UpdateBookingAmountLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
//cief todo: Prototype Period Lock - Starts
$reqData['id'] = $request->route('id');
$dto = new CheckTransferPeriodLockRuleVariant2DTO($reqData);
//cief todo: 110 - Prototype Period Lock - Starts
// $reqData['id'] = $request->route('id');
// $dto = new CheckTransferPeriodLockRuleVariant2DTO($reqData);
$result = $this->ruleEvaluator->evaluate([
$this->canPassTransferPeriodLockRule,
], $dto);
// $result = $this->ruleEvaluator->evaluate([
// $this->canPassTransferPeriodLockRule,
// ], $dto);
if ($result->failed()) {
throw new CriteriaNotFulfilledException("- " . implode("<br>- ", $result->messages()));
}
//cief todo: Prototype Period Lock - Ends
// if ($result->failed()) {
// throw new CriteriaNotFulfilledException("- " . implode("<br>- ", $result->messages()));
// }
//cief todo: 110 - Prototype Period Lock - Ends
$booking = $this->fetchesBooking->execute(['id' => $request->route('id')]);
@@ -6,14 +6,14 @@ use App\Classes\Modules\Bookings\Services\UpdatesBookingFixedAmount;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\Modules\Bookings\Services\FetchesBooking;
use App\Classes\Modules\Bookings\Standards\Rules\CanUpdateBooking;
use App\Classes\Modules\Settings\Services\CreatesKeyValuePair;
use App\Classes\Modules\Settings\Services\UpdatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\CreatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\UpdatesKeyValuePair;
use App\Classes\Modules\Bookings\Services\CalculatesBookingOutstanding;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject;
use App\Classes\ValueObjects\Constants\KVPKey;
use App\Http\Resources\BookingResource;
use Illuminate\Http\JsonResponse;
@@ -7,10 +7,10 @@ use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Jobs\Commands\V2\ProcessPaymentReportV2CommandJob;
use App\Classes\Jobs\Commands\V2\ProcessSalesInvoiceReportV2CommandJob;
use App\Classes\Modules\Settings\Services\CreatesKeyValuePair;
use App\Classes\Modules\Settings\Services\UpdatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\CreatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\UpdatesKeyValuePair;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\Imports\Services\AutoCountDataImport;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\KVPKey;
@@ -4,8 +4,8 @@ namespace App\Classes\Modules\KeyValuePairs\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\Accounts\Services\CreatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\KeyValuePairs\Services\CreatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\CreateChatGPTPromptDTO;
use App\Classes\Modules\KeyValuePairs\Standards\Rules\CanCreateChatGPTPrompt;
use App\Classes\ValueObjects\Constants\KVPKey;
@@ -4,8 +4,8 @@ namespace App\Classes\Modules\KeyValuePairs\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\Accounts\Services\CreatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\KeyValuePairs\Services\CreatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\CreateClaudePromptDTO;
use App\Classes\Modules\KeyValuePairs\Standards\Rules\CanCreateClaudePrompt;
use App\Classes\ValueObjects\Constants\KVPKey;
@@ -1,11 +1,11 @@
<?php
namespace App\Classes\Modules\Settings\ControllersLogic;
namespace App\Classes\Modules\KeyValuePairs\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\Bookings\Standards\Rules\CanCreateBooking;
use App\Classes\Modules\Settings\Services\CreatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\CreatesKeyValuePair;
use App\Classes\ValueObjects\Constants\KVPKey;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -50,6 +50,8 @@ class CreateLockLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
// cief todo: 110 - CanCreateLock
// $password = $request->input('password');
// if($password !== 'prototype'){
// throw new AccessForbiddenException('Incorrect Password');
@@ -4,8 +4,8 @@ namespace App\Classes\Modules\KeyValuePairs\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Accounts\Services\DeletesKeyValuePair;
use App\Classes\Modules\Accounts\Services\FetchesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\DeletesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\FetchesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Standards\Rules\CanDeleteChatGPTPrompt;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -4,8 +4,8 @@ namespace App\Classes\Modules\KeyValuePairs\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Accounts\Services\DeletesKeyValuePair;
use App\Classes\Modules\Accounts\Services\FetchesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\DeletesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\FetchesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Standards\Rules\CanDeleteClaudePrompt;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -1,6 +1,6 @@
<?php
namespace App\Classes\Modules\Settings\ControllersLogic;
namespace App\Classes\Modules\KeyValuePairs\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
@@ -49,6 +49,8 @@ class FetchLockLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
// cief todo: 110 - CanFetchLock
// $this->canFetchBooking->passes();
// $query = $this->fetchesKeyValuePair->execute(['marking' => $request->route('marking'), 'with_transactions' => true]);
@@ -1,10 +1,10 @@
<?php
namespace App\Classes\Modules\Settings\ControllersLogic;
namespace App\Classes\Modules\KeyValuePairs\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Settings\Services\ListsKeyValuePairs;
use App\Classes\Modules\KeyValuePairs\Services\ListsKeyValuePairs;
use App\Classes\Modules\ServiceTypes\Standards\Rules\CanListServiceTypes;
use App\Http\Resources\LockResource;
use ErrorException;
@@ -51,6 +51,8 @@ class ListLocksLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
// cief todo: 110 - CanListLocks
// $this->canListServiceTypes->passes();
$query = $this->listsKeyValuePairs->execute($this->listsKeyValuePairs->deserializeFilters($request->input('filters')));
@@ -4,11 +4,11 @@ namespace App\Classes\Modules\KeyValuePairs\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\UpdateChatGPTPromptDTO;
use App\Classes\Modules\KeyValuePairs\Standards\Rules\CanUpdateChatGPTPrompt;
use App\Classes\Modules\Accounts\Services\FetchesKeyValuePair;
use App\Classes\Modules\Settings\Services\UpdatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\FetchesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\UpdatesKeyValuePair;
use App\Http\Resources\ChatGPTPromptResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -4,11 +4,11 @@ namespace App\Classes\Modules\KeyValuePairs\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\UpdateClaudePromptDTO;
use App\Classes\Modules\KeyValuePairs\Standards\Rules\CanUpdateClaudePrompt;
use App\Classes\Modules\Accounts\Services\FetchesKeyValuePair;
use App\Classes\Modules\Settings\Services\UpdatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\FetchesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\UpdatesKeyValuePair;
use App\Http\Resources\ClaudePromptResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -1,13 +1,13 @@
<?php
namespace App\Classes\Modules\Settings\ControllersLogic;
namespace App\Classes\Modules\KeyValuePairs\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\ServiceTypes\Standards\Rules\CanUpdateServiceType;
use App\Classes\Modules\Settings\Services\CreatesKeyValuePair;
use App\Classes\Modules\Settings\Services\UpdatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\CreatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\UpdatesKeyValuePair;
use App\Http\Resources\LockResource;
use App\Models\KeyValuePair;
use Illuminate\Http\JsonResponse;
@@ -58,6 +58,8 @@ class UpdateLockLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
// cief todo: 110 - CanUpdateLock
$key = $request->input('key');
$kvp = KeyValuePair::whereNull('owner_type')
->whereNull('owner_id')
@@ -1,6 +1,6 @@
<?php
namespace App\Classes\Modules\Accounts\DataTransferObjects;
namespace App\Classes\Modules\KeyValuePairs\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
@@ -1,11 +1,11 @@
<?php
namespace App\Classes\Modules\Accounts\Services;
namespace App\Classes\Modules\KeyValuePairs\Services;
use App\Classes\General\Eloquent\AbstractUpdateRelationshipRecord;
use App\Classes\General\Interfaces\KeyValueInterface;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject;
use App\Models\KeyValuePair;
class CreatesKeyValuePair extends AbstractUpdateRelationshipRecord
@@ -1,6 +1,6 @@
<?php
namespace App\Classes\Modules\Accounts\Services;
namespace App\Classes\Modules\KeyValuePairs\Services;
use App\Classes\General\Eloquent\AbstractDeleteRecord;
use App\Models\KeyValuePair;
@@ -1,6 +1,6 @@
<?php
namespace App\Classes\Modules\Accounts\Services;
namespace App\Classes\Modules\KeyValuePairs\Services;
use App\Classes\General\Eloquent\AbstractFetchRecord;
@@ -1,9 +1,9 @@
<?php
namespace App\Classes\Modules\Settings\Services;
namespace App\Classes\Modules\KeyValuePairs\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject;
use App\Models\KeyValuePair;
class UpdatesKeyValuePair extends AbstractUpdateRecord
@@ -1,35 +0,0 @@
<?php
namespace App\Classes\Modules\Settings\Services;
use App\Classes\General\Eloquent\AbstractUpdateRelationshipRecord;
use App\Classes\General\Interfaces\KeyValueInterface;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Models\KeyValuePair;
class CreatesKeyValuePair extends AbstractUpdateRelationshipRecord
{
/**
* @param KeyValueInterface $kv
* @param KeyValuePairObject $object
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(?KeyValueInterface $kv, KeyValuePairObject $object) {
$model = new KeyValuePair();
$model->key = $object->getKey();
$model->value = $object->getValue();
// Owner-less
if (is_null($kv)) {
$model->owner_type = null;
$model->owner_id = null;
$model->save();
return $model;
}
return $this->handler($kv->attributesKVP(), $model);
}
}
@@ -1,34 +0,0 @@
<?php
namespace App\Classes\Modules\Settings\Services;
use App\Classes\General\Eloquent\AbstractFetchRecord;
use Illuminate\Database\Eloquent\Builder;
use App\Models\KeyValuePair;
class FetchesKeyValuePair extends AbstractFetchRecord
{
/** @var KeyValuePair */
private $repository;
/**
* FetchesKeyValuePair constructor.
* @param KeyValuePair $repository
*/
public function __construct(KeyValuePair $repository)
{
$this->repository = $repository;
}
/**
* @return Builder
*/
public function getRepository(): Builder
{
return $this->repository->newQuery();
}
}
@@ -1,34 +0,0 @@
<?php
namespace App\Classes\Modules\Settings\Services;
use App\Classes\General\Eloquent\AbstractListRecord;
use App\Models\KeyValuePair;
use Illuminate\Database\Eloquent\Builder;
class ListsKeyValuePairs extends AbstractListRecord
{
/** @var KeyValuePair */
private $repository;
/**
* ListsKeyValuePairs constructor.
* @param KeyValuePair $repository
*/
public function __construct(KeyValuePair $repository)
{
$this->repository = $repository;
}
/**
* @return Builder
*/
function getRepository(): Builder
{
return $this->repository->newQuery();
}
}
@@ -99,9 +99,9 @@ class CreatePaymentProofDocumentLogic extends AbstractControllerLogic
]
);
//cief todo: Prototype Period Lock - Starts
$this->updateOrCreateKeyValuePair($transaction->owner->booking, KVPKey::BOOKING_IS_LOCKED, 1);
//cief todo: Prototype Period Lock - Ends
//cief todo: 110 - Prototype Period Lock - Starts
// $this->updateOrCreateKeyValuePair($transaction->owner->booking, KVPKey::BOOKING_IS_LOCKED, 1);
//cief todo: 110 - Prototype Period Lock - Ends
// send email to customer
// todo: a function to send a proof to the receipiant, they have to give us a email of the receipiant and also need to submiited purchase order
@@ -24,9 +24,6 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic
/** @var UpdateRefundTransactionStatusProcessor */
private $updateRefundTransactionStatusProcessor;
/** @var CreateInvoiceTransactionV2Processor */
private $createInvoiceTransactionV2Processor;
/**
* UpdateRefundTransactionStatusLogic constructor.
* @param UpdateRefundTransactionStatusProcessor $updateRefundTransactionStatusProcessor
@@ -138,8 +138,8 @@ class CreateInvoiceTransactionV2Processor
->where('type', TransactionType::PURCHASE_ORDER)
->complete()
->first();
if(!$purchaseOrder && $generateEInvoiceRefund){
if(!$purchaseOrder){
//was use for $generateEInvoiceRefund true
$purchaseOrder = $booking->transactions()
->where('type', TransactionType::PURCHASE_ORDER)
@@ -16,12 +16,12 @@ use App\Classes\Modules\Vouchers\Services\CreatesVoucher;
use App\Classes\Modules\Vouchers\Services\FetchesVoucher;
use App\Classes\Modules\Vouchers\Services\UpdatesVoucherCampaign;
use App\Classes\Modules\Rewards\Services\CreatesUserReward;
use App\Classes\Modules\Settings\Services\CreatesKeyValuePair;
use App\Classes\Modules\Settings\Services\UpdatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\CreatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\UpdatesKeyValuePair;
use App\Classes\Modules\Vouchers\Standards\Rules\CanCreateVoucher;
use App\Classes\Modules\Vouchers\DataTransferObjects\ValidateVoucherifyVoucherObject;
use App\Classes\Modules\Vouchers\DataTransferObjects\CreateVoucherObject;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\Vouchers\DataTransferObjects\VoucherCampaignObject;
use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Classes\ValueObjects\Constants\Vouchers;
@@ -2,7 +2,7 @@
namespace App\Classes\Modules\Wallets\Processors;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\KeyValuePairs\DataTransferObjects\KeyValuePairObject;
use App\Models\Wallet;
use App\Models\Company;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
@@ -15,10 +15,11 @@ use App\Classes\Modules\Transactions\Services\CreatesTransaction;
use App\Classes\Modules\Wallets\DataTransferObjects\WalletObject;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
use App\Classes\Modules\Settings\Services\CreatesKeyValuePair;
use App\Classes\Modules\Settings\Services\UpdatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\CreatesKeyValuePair;
use App\Classes\Modules\KeyValuePairs\Services\UpdatesKeyValuePair;
use App\Classes\ValueObjects\Constants\KVPKey;
use App\Models\Transaction;
use Illuminate\Support\Facades\Log;
class CreditWalletProcessor
{
+10 -8
View File
@@ -24,6 +24,16 @@ class KVPKey
public const BOOKING_EINVOICE_ELIGIBLE = 'BOOKING_EINVOICE_ELIGIBLE';
public const AUTOCOUNT_DOCNO_SALES_DEPOSIT_BY_WALLET_OFFICIAL_RECEIPT = 'AUTOCOUNT_DOCNO_SALES_DEPOSIT_BY_WALLET_OR';
public const AUTOCOUNT_DOCNO_SALES_DEPOSIT_BY_WALLET_REFUND = 'AUTOCOUNT_DOCNO_SALES_DEPOSIT_BY_WALLET_RF';
public const CHATGPT_PROMPT_PREFIX = 'CHATGPT_PROMPT_';
public const CLAUDE_PROMPT_PREFIX = 'CLAUDE_PROMPT_';
public const BOOKING_AMOUNT_UPDATE = 'BOOKING_AMOUNT_UPDATE';
public const BOOKING_IS_LOCKED = 'BOOKING_IS_LOCKED';
public const UI_SUPPLIER_PAID_CURRENCY_ORDER_TAB_IS_LOCKED = 'UI_SUPPLIER_PAID_CURRENCY_ORDER_TAB_IS_LOCKED';
@@ -32,12 +42,4 @@ class KVPKey
public const UI_PAYMENTS_OPEN_CURRENCY_ORDERS_IS_LOCKED = 'UI_PAYMENTS_OPEN_CURRENCY_ORDERS_IS_LOCKED';
public const AUTOCOUNT_DOCNO_SALES_DEPOSIT_BY_WALLET_OFFICIAL_RECEIPT = 'AUTOCOUNT_DOCNO_SALES_DEPOSIT_BY_WALLET_OR';
public const AUTOCOUNT_DOCNO_SALES_DEPOSIT_BY_WALLET_REFUND = 'AUTOCOUNT_DOCNO_SALES_DEPOSIT_BY_WALLET_RF';
public const BOOKING_AMOUNT_UPDATE = 'BOOKING_AMOUNT_UPDATE';
public const CHATGPT_PROMPT_PREFIX = 'CHATGPT_PROMPT_';
public const CLAUDE_PROMPT_PREFIX = 'CLAUDE_PROMPT_';
}
@@ -9,7 +9,6 @@ use Illuminate\Http\Request;
class CreateSystemUserController
{
/**
* @param Request $request
* @param CreateSystemUserLogic $logic
@@ -3,35 +3,21 @@
namespace App\Http\Controllers\Affiliate;
use App\Classes\Modules\Affiliate\ControllersLogic\CreateAffiliateLogic;
use App\Http\Requests\CreateAffiliateRequest;
use App\Models\Affiliate;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class CreateAffiliateController
{
/**
* @param CreateAffiliateRequest $request
* @param Request $request
* @param CreateAffiliateLogic $logic
* @return JsonResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function create(CreateAffiliateRequest $request, CreateAffiliateLogic $logic): JsonResponse {
$this->authorize('create', Affiliate::class);
return $logic->execute($request);
}
/**
* Authorize a given action for the current user.
*
* @param mixed $ability
* @param mixed|array $arguments
* @return \Illuminate\Auth\Access\Response
*
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function authorize($ability, $arguments = [])
public function create(Request $request, CreateAffiliateLogic $logic): JsonResponse
{
return app(\Illuminate\Contracts\Auth\Access\Gate::class)->authorize($ability, $arguments);
return $logic->execute($request);
}
}
@@ -1,8 +1,8 @@
<?php
namespace App\Http\Controllers\Settings;
namespace App\Http\Controllers\KeyValuePairs;
use App\Classes\Modules\Settings\ControllersLogic\CreateLockLogic;
use App\Classes\Modules\KeyValuePairs\ControllersLogic\CreateLockLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -1,8 +1,8 @@
<?php
namespace App\Http\Controllers\Settings;
namespace App\Http\Controllers\KeyValuePairs;
use App\Classes\Modules\Settings\ControllersLogic\FetchLockLogic;
use App\Classes\Modules\KeyValuePairs\ControllersLogic\FetchLockLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -1,8 +1,8 @@
<?php
namespace App\Http\Controllers\Settings;
namespace App\Http\Controllers\KeyValuePairs;
use App\Classes\Modules\Settings\ControllersLogic\ListLocksLogic;
use App\Classes\Modules\KeyValuePairs\ControllersLogic\ListLocksLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -1,8 +1,8 @@
<?php
namespace App\Http\Controllers\Settings;
namespace App\Http\Controllers\KeyValuePairs;
use App\Classes\Modules\Settings\ControllersLogic\UpdateLockLogic;
use App\Classes\Modules\KeyValuePairs\ControllersLogic\UpdateLockLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -7,6 +7,7 @@ use App\Classes\Modules\Rules\ControllersLogic\CheckPurchaseOrderRuleLogic;
use App\Classes\Modules\Rules\ControllersLogic\CheckTransferRuleLogic;
use App\Classes\Modules\Rules\ControllersLogic\CheckTransferPeriodLockRuleLogic;
use App\Classes\Modules\Rules\ControllersLogic\CheckEInvoiceAmountLimitLogic;
use App\Classes\Modules\Rules\ControllersLogic\CheckTransferPeriodLockRuleLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -56,4 +57,13 @@ class CheckRuleController
public function checkEInvoiceAmountLimitRule(Request $request, CheckEInvoiceAmountLimitLogic $logic): JsonResponse {
return $logic->execute($request);
}
/**
* @param Request $request
* @param CheckTransferPeriodLockRuleLogic $logic
* @return JsonResponse
*/
public function checkTransferPeriodLockRule(Request $request, CheckTransferPeriodLockRuleLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
@@ -31,7 +31,6 @@ class CreateAffiliateRequest extends FormRequest
'min:3',
'max:255',
'regex:/^[a-zA-Z0-9_-]+$/',
'unique:affiliates,code,NULL,id,deleted_at,NULL'
],
'campaign_name' => 'required|string|max:255',
'campaign_description' => 'nullable|string|max:65535',
Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

@@ -205,7 +205,9 @@
},
submitForm(){
this.step === 2 ? this.submit(this.route('api.account.registration.register'), 'post', 'registrationSection', false, false) : this.changeStep('next');
const urlParams = new URLSearchParams(window.location.search);
const tracking = urlParams.get('tracking');
this.step === 2 ? this.submit(this.route('api.account.registration.register') + (tracking ? '?tracking=' + tracking : ''), 'post', 'registrationSection', false, false) : this.changeStep('next');
},
successHandler(response){
// fire to gtag manager for fb pixel tracking: CompleteRegistration
@@ -195,7 +195,7 @@
<!-- Approve and Edit Purchase Order -->
<div class="row" v-if="submitted">
<div class="col-12 col-md-5 pr-md-0" v-if="submitted && data.status !== 3">
<div class="col-12 col-md-5 pr-md-0" v-if="submitted">
<div class="row m-b-15" v-if="($store.getters.isAdmin && data.purchase_order.status === 1) || ($store.getters.isCustomer && data.purchase_order.status === 1 && $store.getters.getCompanyId === 199)" >
<div class="col">
<button class="btn btn-sm btn-block btn-success b-rad-none" :disabled="poProcessing" @click="handleRepprove()">Approve Purchase Order</button>
@@ -1,8 +1,8 @@
<template>
<div class="row parentContainer">
<div class="col">
<!-- cief todo: Prototype Period Lock - Starts -->
<button v-if="booking && !locked && lockInitialized && $store.getters.isAdmin" @click="lock">
<!-- cief todo: 110 - Prototype Period Lock - Starts -->
<!-- <button v-if="booking && !locked && lockInitialized && $store.getters.isAdmin" @click="lock">
🔒 Lock Page
</button>
@@ -14,8 +14,8 @@
:password="''"
v-on:lock="lock"
v-on:initializeLock="initializeLock">
</page-lock>
<!-- cief todo: Prototype Period Lock - Ends -->
</page-lock> -->
<!-- cief todo: 110 - Prototype Period Lock - Ends -->
<loading-component style="height: 200px; top: 0;" key="1" color="success" v-show="isLoading"></loading-component>
<div class="row" v-show="!isLoading" v-if="booking">
<div class="col-md col-sm-12 m-b-20">
@@ -42,6 +42,28 @@
</modal-form-component>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<div class="row">
<div class="col p-r-0">
<div class="form-group no-margin form-group-default b-rad-none">
<label class="text-primary">Search</label>
<input type="text" class="form-control" v-model="searchTerm" @keyup.enter="search" placeholder="Search by campaign name, code, or description"/>
</div>
</div>
<div class="col-auto p-l-0 p-r-0">
<div class="btn btn-primary b-rad-none" @click="search">
<i class="fa fa-search lh-40"></i>
</div>
</div>
<div class="col-auto p-l-0">
<div class="btn btn-secondary b-rad-none" @click="reset">
<i class="fa fa-remove lh-40"></i>
</div>
</div>
</div>
</div>
</div>
<div class="row m-b-10 b-b p-b-5" style="border-color: #e0e0e0 !important;">
<div class="col-2">
<div class="font-heading all-caps fs-9 muted">Campaign</div>
@@ -71,7 +93,7 @@
</div>
<div class="row m-b-20">
<div class="col">
<list-component section="affiliatesSection" :endpoint="route('api.affiliate.list')" :key="refreshKey">
<list-component section="affiliatesSection" :endpoint="route('api.affiliate.list')" :key="refreshKey" :options="options">
<template slot="list" slot-scope="{data}">
<affiliate-single-item-component section="affiliatesSection" :data="data"></affiliate-single-item-component>
</template>
@@ -89,12 +111,27 @@
data() {
return {
refreshKey: 1,
searchTerm: '',
options: {}
}
},
methods: {
refreshAffiliateCodes() {
this.refreshKey++;
},
search() {
if (this.searchTerm && this.searchTerm.trim()) {
this.options['affiliate_search'] = this.searchTerm.trim();
} else {
delete this.options['affiliate_search'];
}
this.refreshKey++;
},
reset() {
this.searchTerm = '';
delete this.options['affiliate_search'];
this.refreshKey++;
}
}
}
</script>
</script>
@@ -195,7 +195,21 @@
errorHandler(error) {
// Don't reload the list on error - just handle the error message
this.isLoading = false;
this.errorMessageHandler(error);
// Parse error message properly
let errorMessage = error.message || error;
// If error.message is a JSON string, parse it
if (typeof errorMessage === 'string') {
try {
const parsed = JSON.parse(errorMessage);
errorMessage = parsed.message || errorMessage;
} catch (e) {
// If parsing fails, use the message as-is
}
}
this.errorMessageHandler(errorMessage);
},
resetForm() {
if (this.$v) {
@@ -215,7 +229,7 @@
if (!this.validate()) {
return;
}
const url = this.parameters.id
const url = this.parameters.id
? this.route('api.affiliate.update', this.parameters.id)
: this.route('api.affiliate.create');
const method = this.parameters.id ? 'put' : 'post';
@@ -0,0 +1,925 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Primary Meta Tags -->
<title>1688支付替代方案 - 马币直付 | CIEF Source 官方授权代付服务</title>
<meta name="title" content="1688支付替代方案 - 马币直付 | CIEF Source 官方授权代付服务">
<meta name="description" content="无需开通支付宝,无需处理外汇。用马币(MYR)完成人民币代付1688订单,订单状态秒级同步,发票合规可对账。官方授权,安全合规,10,000+成功代付案例。">
<meta name="keywords" content="1688支付,1688代付,马币支付1688,1688支付替代方案,支付宝替代,1688人民币代付,马来西亚1688支付,CIEF Source,1688订单支付,跨境支付">
<meta name="author" content="CIEF Source">
<meta name="robots" content="index, follow">
<meta name="language" content="Chinese">
<!-- Canonical URL -->
<link rel="canonical" href="{{ url('/1688-payment-alternative-cn') }}">
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:url" content="{{ url('/1688-payment-alternative-cn') }}">
<meta property="og:title" content="1688支付替代方案 - 马币直付 | CIEF Source">
<meta property="og:description" content="无需开通支付宝,无需处理外汇。用马币完成人民币代付1688订单,订单状态秒级同步,发票合规可对账。">
<meta property="og:locale" content="zh_CN">
<meta property="og:site_name" content="CIEF Source">
<!-- Twitter -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:url" content="{{ url('/1688-payment-alternative-cn') }}">
<meta name="twitter:title" content="1688支付替代方案 - 马币直付 | CIEF Source">
<meta name="twitter:description" content="无需开通支付宝,无需处理外汇。用马币完成人民币代付1688订单,订单状态秒级同步,发票合规可对账。">
<!-- Favicon -->
<link rel="apple-touch-icon" sizes="180x180" href="{{ asset('images/favicon/apple-touch-icon.png') }}">
<link rel="icon" type="image/png" sizes="32x32" href="{{ asset('images/favicon/favicon-32x32.png') }}">
<link rel="icon" type="image/png" sizes="16x16" href="{{ asset('images/favicon/favicon-16x16.png') }}">
<link rel="manifest" href="/site.webmanifest">
<!-- Preconnect for Performance -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="dns-prefetch" href="https://www.googletagmanager.com">
<!-- Structured Data (JSON-LD) -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Service",
"name": "1688支付替代方案",
"description": "无需开通支付宝,无需处理外汇。用马币(MYR)完成人民币代付1688订单,订单状态秒级同步,发票合规可对账。",
"provider": {
"@type": "Organization",
"name": "CIEF Source",
"url": "{{ url('/') }}"
},
"areaServed": {
"@type": "Country",
"name": "Malaysia"
},
"serviceType": "跨境支付服务"
}
</script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [{
"@type": "Question",
"name": "代付安全吗?",
"acceptedAnswer": {
"@type": "Answer",
"text": "CIEF 通过阿里官方 API 进行代付,支付记录与订单回执全链路可追踪。"
}
}, {
"@type": "Question",
"name": "汇率如何计算?",
"acceptedAnswer": {
"@type": "Answer",
"text": "系统每日更新官方汇率;确认前可在界面预览最终金额。"
}
}, {
"@type": "Question",
"name": "是否提供马来西亚发票?",
"acceptedAnswer": {
"@type": "Answer",
"text": "支持开具马来西亚正规发票,便于会计与审计对账。"
}
}, {
"@type": "Question",
"name": "是否有最低代付金额?",
"acceptedAnswer": {
"@type": "Answer",
"text": "无最低限制,小至单笔订单亦可受理。"
}
}, {
"@type": "Question",
"name": "代付后如何跟进发货?",
"acceptedAnswer": {
"@type": "Answer",
"text": "订单与发货信息会回传至 CIEF Source,你可在同一系统继续安排清关与配送。"
}
}]
}
</script>
<style>
/* === CSS Variables === */
:root {
--primary: #22c55e;
--secondary: #38bdf8;
--dark: #0f172a;
--dark-card: #1e293b;
--text: #e2e8f0;
--text-muted: #94a3b8;
--border: #334155;
--radius: 16px;
}
/* === Reset & Base === */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Microsoft YaHei", sans-serif;
background: linear-gradient(180deg, #0f172a 0%, #1e293b 100%);
color: var(--text);
line-height: 1.6;
min-height: 100vh;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
width: 100%;
}
img { max-width: 100%; height: auto; }
a { text-decoration: none; color: inherit; }
/* === Typography === */
.heading-xl {
font-size: clamp(32px, 5vw, 52px);
line-height: 1.2;
font-weight: 700;
margin-bottom: 20px;
color: var(--text);
}
.heading-lg {
font-size: clamp(24px, 4vw, 36px);
line-height: 1.3;
font-weight: 700;
margin-bottom: 16px;
color: var(--text);
}
.heading-md {
font-size: clamp(20px, 3vw, 28px);
line-height: 1.4;
font-weight: 600;
margin-bottom: 12px;
color: var(--text);
}
.text-lg {
font-size: clamp(16px, 2.5vw, 20px);
color: #cbd5e1;
}
.text-muted {
color: var(--text-muted);
font-size: 15px;
}
/* === Buttons === */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 14px 28px;
border-radius: 100px;
font-weight: 600;
font-size: 16px;
transition: all 0.3s ease;
cursor: pointer;
border: 2px solid transparent;
}
.btn-primary {
background: linear-gradient(135deg, var(--primary), #16a34a);
color: #0a2e19;
box-shadow: 0 8px 20px rgba(34, 197, 94, 0.3);
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 12px 28px rgba(34, 197, 94, 0.4);
}
.btn-secondary {
background: rgba(148, 163, 184, 0.1);
border-color: var(--border);
color: var(--text);
}
.btn-secondary:hover {
background: rgba(148, 163, 184, 0.15);
border-color: #475569;
}
/* === Badges & Pills === */
.badge {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 8px 16px;
background: rgba(34, 197, 94, 0.1);
border: 1px solid rgba(34, 197, 94, 0.3);
border-radius: 100px;
color: #86efac;
font-size: 13px;
font-weight: 500;
margin-bottom: 20px;
}
.pill {
display: inline-block;
padding: 6px 14px;
background: rgba(56, 189, 248, 0.1);
border: 1px solid rgba(56, 189, 248, 0.3);
border-radius: 100px;
color: #7dd3fc;
font-size: 13px;
font-weight: 500;
margin-bottom: 12px;
}
/* === Cards === */
.card {
background: linear-gradient(180deg, rgba(30, 41, 59, 0.8), rgba(15, 23, 42, 0.6));
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 24px;
transition: all 0.3s ease;
}
.card:hover {
transform: translateY(-2px);
border-color: #475569;
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.4);
}
/* === Grid System === */
.grid {
display: grid;
gap: 20px;
}
.grid-2 { grid-template-columns: 1fr; }
.grid-3 { grid-template-columns: 1fr; }
@media (min-width: 640px) {
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 900px) {
.grid-3 { grid-template-columns: repeat(3, 1fr); }
}
/* === Sections === */
.section {
padding: 80px 0;
position: relative;
}
.section-sm { padding: 50px 0; }
/* === Hero Section === */
.hero {
padding: 100px 0 80px;
position: relative;
overflow: hidden;
}
.hero::before {
content: '';
position: absolute;
top: -20%;
right: -10%;
width: 800px;
height: 800px;
background: radial-gradient(circle, rgba(34, 197, 94, 0.15), transparent 70%);
filter: blur(60px);
pointer-events: none;
}
.hero::after {
content: '';
position: absolute;
bottom: -20%;
left: -10%;
width: 600px;
height: 600px;
background: radial-gradient(circle, rgba(56, 189, 248, 0.12), transparent 70%);
filter: blur(50px);
pointer-events: none;
}
.hero-content {
position: relative;
z-index: 1;
}
.hero-grid {
display: grid;
gap: 40px;
align-items: center;
}
@media (min-width: 900px) {
.hero-grid { grid-template-columns: 1.2fr 1fr; }
}
/* === Stats === */
.stats {
display: flex;
gap: 16px;
flex-wrap: wrap;
margin-top: 24px;
}
.stat-item {
padding: 10px 16px;
background: rgba(99, 102, 241, 0.1);
border: 1px dashed rgba(129, 140, 248, 0.3);
border-radius: 12px;
color: #a5b4fc;
font-size: 14px;
font-weight: 500;
}
/* === Feature Items === */
.feature-item {
display: flex;
gap: 16px;
align-items: flex-start;
}
.feature-icon {
flex-shrink: 0;
width: 48px;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
background: rgba(56, 189, 248, 0.1);
border: 1px solid rgba(56, 189, 248, 0.3);
border-radius: 12px;
font-size: 24px;
}
/* === Flow Diagram === */
.flow-card {
background: rgba(15, 23, 42, 0.6);
border: 1px solid var(--border);
border-radius: 14px;
padding: 20px;
}
.flow-step {
display: flex;
gap: 16px;
align-items: flex-start;
padding: 16px;
background: rgba(30, 41, 59, 0.5);
border: 1px solid var(--border);
border-radius: 12px;
margin-bottom: 12px;
}
.flow-step:last-child { margin-bottom: 0; }
.step-number {
flex-shrink: 0;
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
background: rgba(56, 189, 248, 0.15);
border: 1px solid rgba(56, 189, 248, 0.4);
border-radius: 10px;
color: #7dd3fc;
font-weight: 700;
font-size: 16px;
}
.flow-arrow {
text-align: center;
color: var(--secondary);
font-size: 24px;
margin: -6px 0;
}
/* === Diagram Box === */
.diagram-box {
background: linear-gradient(180deg, rgba(30, 41, 59, 0.7), rgba(15, 23, 42, 0.5));
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 24px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
}
.node {
display: flex;
justify-content: space-between;
align-items: center;
gap: 12px;
padding: 14px 16px;
background: rgba(30, 41, 59, 0.5);
border: 1px solid var(--border);
border-radius: 12px;
margin-bottom: 8px;
}
.node:last-child { margin-bottom: 0; }
.node-badge {
padding: 4px 12px;
background: rgba(34, 197, 94, 0.15);
border: 1px solid rgba(34, 197, 94, 0.3);
border-radius: 8px;
color: #86efac;
font-size: 12px;
font-weight: 500;
}
/* === Table === */
.table-wrap {
overflow-x: auto;
margin-top: 24px;
}
table {
width: 100%;
border-collapse: collapse;
background: rgba(30, 41, 59, 0.6);
border: 2px solid var(--border);
border-radius: 12px;
overflow: hidden;
}
table th,
table td {
padding: 16px;
text-align: left;
border: 1px solid var(--border);
}
table th {
background: rgba(15, 23, 42, 0.8);
color: var(--text);
font-weight: 600;
}
table tr:last-child td {
border-bottom: none;
}
table tr:hover {
background: rgba(30, 41, 59, 0.8);
}
/* === FAQ === */
.faq-item {
background: rgba(30, 41, 59, 0.6);
border: 1px solid var(--border);
border-radius: 12px;
padding: 16px;
margin-bottom: 12px;
}
.faq-question {
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
font-weight: 600;
color: var(--text);
}
.faq-question span {
font-size: 20px;
color: var(--secondary);
transition: transform 0.3s ease;
}
.faq-item.active .faq-question span {
transform: rotate(45deg);
}
.faq-answer {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease;
margin-top: 12px;
color: var(--text-muted);
line-height: 1.6;
}
.faq-item.active .faq-answer {
max-height: 500px;
padding-top: 12px;
}
/* === CTA Banner === */
.cta-banner {
background: linear-gradient(135deg, rgba(34, 197, 94, 0.15), rgba(56, 189, 248, 0.1));
border: 1px solid rgba(34, 197, 94, 0.3);
border-radius: 24px;
padding: 50px 30px;
text-align: center;
}
.cta-buttons {
display: flex;
gap: 16px;
justify-content: center;
flex-wrap: wrap;
margin-top: 24px;
}
/* === Footer === */
.footer {
padding: 40px 0;
border-top: 1px solid var(--border);
color: var(--text-muted);
font-size: 14px;
text-align: center;
}
/* === Utilities === */
.text-center { text-align: center; }
.mb-0 { margin-bottom: 0; }
.mb-1 { margin-bottom: 8px; }
.mb-2 { margin-bottom: 16px; }
.mb-3 { margin-bottom: 24px; }
.mt-2 { margin-top: 16px; }
.mt-3 { margin-top: 24px; }
.gap-2 { gap: 16px; }
.flex { display: flex; }
.flex-wrap { flex-wrap: wrap; }
.highlight { color: var(--primary); }
</style>
</head>
<body>
<!-- Hero Section -->
<section class="hero">
<div class="container hero-content">
<div class="hero-grid">
<div>
<span class="badge"> 官方授权 · 安全合规 · 马币直付</span>
<h1 class="heading-xl">
无法支付 1688 订单?<br>
<span class="highlight">CIEF 支付替代方案</span> 一键搞定
</h1>
<p class="text-lg">
无需开通支付宝,无需处理外汇。用马币(MYR)完成人民币代付,订单状态秒级同步,发票合规可对账。
</p>
<div class="flex flex-wrap gap-2 mt-3">
<a href="#start" class="btn btn-primary">
开始代付 1688 订单
</a>
<a href="https://wa.me/60123456789" class="btn btn-secondary" target="_blank" rel="noopener">
WhatsApp 咨询
</a>
</div>
<div class="stats">
<div class="stat-item">🎯 10,000+ 成功代付</div>
<div class="stat-item"> API 直连 · 可追踪</div>
<div class="stat-item">🧾 马来西亚正规发票</div>
</div>
</div>
<div class="diagram-box">
<div class="node">
<strong>买家(你)</strong>
<span class="node-badge">MYR 付款</span>
</div>
<div class="flow-arrow"></div>
<div class="node">
<strong>CIEF 系统</strong>
<span class="node-badge">API 处理</span>
</div>
<div class="flow-arrow"></div>
<div class="node">
<strong>1688 卖家</strong>
<span class="node-badge">RMB 收款</span>
</div>
<div class="flow-arrow"></div>
<div class="node">
<strong>物流清关</strong>
<span class="node-badge">一条龙</span>
</div>
<p class="text-muted" style="margin-top: 16px; font-size: 13px;">
💡 提示:可在 CIEF Source 内直接跟踪订单状态与物流进度
</p>
</div>
</div>
</div>
</section>
<!-- Pain Points -->
<section class="section">
<div class="container">
<span class="pill">常见难题</span>
<h2 class="heading-lg">你是否也遇到这些支付障碍?</h2>
<p class="text-muted mb-3">跨境采购最常见的痛点,我们都已替客户解决过:</p>
<div class="grid grid-2">
<div class="card">
<div class="feature-item">
<div class="feature-icon">🚫</div>
<div>
<h3 class="heading-md mb-1">无法开通/使用支付宝</h3>
<p class="text-muted">没有中国手机号或资质,支付宝难以落地。</p>
</div>
</div>
</div>
<div class="card">
<div class="feature-item">
<div class="feature-icon">🏢</div>
<div>
<h3 class="heading-md mb-1">公司账户难以对外汇款</h3>
<p class="text-muted">银行外汇手续复杂、到账慢、沟通成本高。</p>
</div>
</div>
</div>
<div class="card">
<div class="feature-item">
<div class="feature-icon">⏱️</div>
<div>
<h3 class="heading-md mb-1">时效 & 可追踪性差</h3>
<p class="text-muted">传统"找人代付"风险高、无法系统化追踪。</p>
</div>
</div>
</div>
<div class="card">
<div class="feature-item">
<div class="feature-icon">🧾</div>
<div>
<h3 class="heading-md mb-1">发票与对账不合规</h3>
<p class="text-muted">无法拿到马来西亚发票,财务对账困难。</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Solution -->
<section class="section">
<div class="container">
<span class="pill">解决方案</span>
<h2 class="heading-lg">官方授权 · 安全合规的 1688 支付替代方案</h2>
<p class="text-muted mb-3">
CIEF 作为 1688 官方合作方,支持你用马币完成人民币代付,付款即刻同步订单状态,并可无缝衔接采购、清关与配送。
</p>
<div class="grid grid-2">
<div class="flow-card">
<div class="flow-step">
<div class="step-number">1</div>
<div>
<strong>提交 1688 订单链接</strong>
<p class="text-muted mb-0"> CIEF Source 粘贴链接或上传截图,便可开始。</p>
</div>
</div>
<div class="flow-step">
<div class="step-number">2</div>
<div>
<strong>确认金额与汇率</strong>
<p class="text-muted mb-0">系统显示代付金额(含当日汇率),确认无误即下一步。</p>
</div>
</div>
<div class="flow-step">
<div class="step-number">3</div>
<div>
<strong>用马币付款给 CIEF</strong>
<p class="text-muted mb-0">支持转账/FPX 等方式,企业可走公司账。</p>
</div>
</div>
<div class="flow-step">
<div class="step-number">4</div>
<div>
<strong>API 代你支付卖家</strong>
<p class="text-muted mb-0">Ali 官方 API 直连,安全稳定可追踪。</p>
</div>
</div>
<div class="flow-step">
<div class="step-number">5</div>
<div>
<strong>订单与物流状态同步</strong>
<p class="text-muted mb-0">代付完成后,订单状态与发货信息自动回传。</p>
</div>
</div>
</div>
<div class="grid">
<div class="card">
<div class="feature-item">
<div class="feature-icon">💵</div>
<div>
<h3 class="heading-md mb-1">马币直付</h3>
<p class="text-muted mb-0">无需人民币账户,无需外汇繁琐流程。</p>
</div>
</div>
</div>
<div class="card">
<div class="feature-item">
<div class="feature-icon">🔒</div>
<div>
<h3 class="heading-md mb-1">官方 API</h3>
<p class="text-muted mb-0">阿里官方接口,支付与回执全链路记录。</p>
</div>
</div>
</div>
<div class="card">
<div class="feature-item">
<div class="feature-icon"></div>
<div>
<h3 class="heading-md mb-1">秒级入账</h3>
<p class="text-muted mb-0">确认后快速代付,缩短采购周期。</p>
</div>
</div>
</div>
<div class="card">
<div class="feature-item">
<div class="feature-icon">🧾</div>
<div>
<h3 class="heading-md mb-1">马来西亚发票</h3>
<p class="text-muted mb-0">开具正规发票,方便会计与审计对账。</p>
</div>
</div>
</div>
</div>
</div>
<div class="flex flex-wrap gap-2 mt-3">
<a href="#start" class="btn btn-primary">
现在用马币代付
</a>
<a href="https://wa.me/60123456789" class="btn btn-secondary" target="_blank" rel="noopener">
咨询客服
</a>
</div>
</div>
</section>
<!-- Comparison Table -->
<section class="section-sm">
<div class="container">
<span class="pill">为什么选我们</span>
<h2 class="heading-lg">一眼看懂:传统方式 vs CIEF 方案</h2>
<div class="table-wrap">
<table>
<thead>
<tr>
<th>项目</th>
<th>传统方式</th>
<th>CIEF 支付替代方案</th>
</tr>
</thead>
<tbody>
<tr>
<td>开通支付宝</td>
<td>需中国手机号/身份证,流程复杂</td>
<td><strong style="color: var(--primary);">无需</strong>,直接用马币支付</td>
</tr>
<tr>
<td>外汇手续</td>
<td>流程长、沟通成本高</td>
<td><strong style="color: var(--primary);">省去外汇步骤</strong>,企业可走公司账</td>
</tr>
<tr>
<td>安全性</td>
<td>找人代付,风险与纠纷高</td>
<td><strong style="color: var(--primary);">官方 API</strong> 直连,支付有据可查</td>
</tr>
<tr>
<td>订单追踪</td>
<td>支付后信息割裂,不易追踪</td>
<td><strong style="color: var(--primary);">系统实时回传</strong> 下单/发货状态</td>
</tr>
<tr>
<td>发票对账</td>
<td>无法取得本地发票</td>
<td><strong style="color: var(--primary);">马来西亚正规发票</strong>,合规对账</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<!-- Social Proof -->
<section class="section-sm">
<div class="container">
<div class="grid grid-3">
<div class="card text-center">
<h3 class="heading-md">1688 官方合作伙伴</h3>
<p class="text-muted mb-0">长期技术与业务合作,可信赖的跨境解决方案。</p>
</div>
<div class="card text-center">
<h3 class="heading-md">10,000+ 成功代付</h3>
<p class="text-muted mb-0">覆盖多行业客户,口碑沉淀与流程完善。</p>
</div>
<div class="card text-center">
<h3 class="heading-md">端到端一条龙</h3>
<p class="text-muted mb-0">采购、代付、清关、配送与对账,全流程打通。</p>
</div>
</div>
</div>
</section>
<!-- FAQ -->
<section class="section">
<div class="container">
<span class="pill">FAQ</span>
<h2 class="heading-lg">常见问题</h2>
<div class="grid">
<div class="faq-item">
<div class="faq-question" onclick="this.parentElement.classList.toggle('active')">
代付安全吗?
<span>+</span>
</div>
<div class="faq-answer">
CIEF 通过阿里官方 API 进行代付,支付记录与订单回执全链路可追踪。
</div>
</div>
<div class="faq-item">
<div class="faq-question" onclick="this.parentElement.classList.toggle('active')">
汇率如何计算?
<span>+</span>
</div>
<div class="faq-answer">
系统每日更新官方汇率;确认前可在界面预览最终金额。
</div>
</div>
<div class="faq-item">
<div class="faq-question" onclick="this.parentElement.classList.toggle('active')">
是否提供马来西亚发票?
<span>+</span>
</div>
<div class="faq-answer">
支持开具马来西亚正规发票,便于会计与审计对账。
</div>
</div>
<div class="faq-item">
<div class="faq-question" onclick="this.parentElement.classList.toggle('active')">
是否有最低代付金额?
<span>+</span>
</div>
<div class="faq-answer">
无最低限制,小至单笔订单亦可受理。
</div>
</div>
<div class="faq-item">
<div class="faq-question" onclick="this.parentElement.classList.toggle('active')">
代付后如何跟进发货?
<span>+</span>
</div>
<div class="faq-answer">
订单与发货信息会回传至 CIEF Source,你可在同一系统继续安排清关与配送。
</div>
</div>
</div>
</div>
</section>
<!-- CTA Banner -->
<section class="section-sm">
<div class="container">
<div class="cta-banner">
<h2 class="heading-lg mb-2">让采购更简单、安全、合规</h2>
<p class="text-lg mb-0">现在就用马币为你的 1688 订单代付,并在同一平台完成清关与对账。</p>
<div class="cta-buttons">
<a href="#start" class="btn btn-primary">开始使用</a>
<a href="https://wa.me/60123456789" class="btn btn-secondary" target="_blank" rel="noopener">联系客服</a>
</div>
</div>
</div>
</section>
<!-- Footer -->
<footer class="footer">
<div class="container">
<p>&copy; {{ date('Y') }} CIEF Source. All rights reserved.</p>
<p>1688 官方授权支付替代方案服务商</p>
</div>
</footer>
</body>
</html>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+48 -4
View File
@@ -78,6 +78,29 @@
</div>
</div>
</div>
<div class="row m-b-5" v-if="$store.getters.isAdmin">
<div class="col">
<div class="row">
<div class="col">
<div class="row">
<div class="col bg-master-light tabButton" tab-name="affiliateSettings">
<div class="row align-items-center">
<div class="col-auto p-t-10 p-b-10 b-r b-grey">
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
width="35" height="35"
viewBox="0 0 172 172"
style=" fill:#000000;"><defs><linearGradient x1="86" y1="28.55469" x2="86" y2="143.10938" gradientUnits="userSpaceOnUse" id="color-4_affiliate_gr4"><stop offset="0" stop-color="#009add"></stop><stop offset="1" stop-color="#00baa4"></stop></linearGradient></defs><g fill="none" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><path d="M0,172v-172h172v172z" fill="none"></path><g><path d="M86,21.5c-35.56369,0 -64.5,28.93631 -64.5,64.5c0,35.56369 28.93631,64.5 64.5,64.5c35.56369,0 64.5,-28.93631 64.5,-64.5c0,-35.56369 -28.93631,-64.5 -64.5,-64.5zM86,32.25c29.63631,0 53.75,24.11369 53.75,53.75c0,29.63631 -24.11369,53.75 -53.75,53.75c-29.63631,0 -53.75,-24.11369 -53.75,-53.75c0,-29.63631 24.11369,-53.75 53.75,-53.75zM86,48.375c-20.81887,0 -37.625,16.80613 -37.625,37.625c0,20.81887 16.80613,37.625 37.625,37.625c20.81887,0 37.625,-16.80613 37.625,-37.625c0,-20.81887 -16.80613,-37.625 -37.625,-37.625zM86,59.125c14.81887,0 26.875,12.05613 26.875,26.875c0,14.81887 -12.05613,26.875 -26.875,26.875c-14.81887,0 -26.875,-12.05613 -26.875,-26.875c0,-14.81887 12.05613,-26.875 26.875,-26.875z" fill="url(#color-4_affiliate_gr4)"></path></g></g></svg>
</div>
<div class="col">
<div class="fs-12 m-t-5 all-caps m-b-5">Affiliate</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<template v-if="$store.getters.isSuperAdmin">
<div class="row m-b-5">
<div class="col">
@@ -248,10 +271,31 @@
<div class="col bg-master-light tabButton" tab-name="aiPrompts">
<div class="row align-items-center">
<div class="col-auto p-t-10 p-b-10 b-r b-grey">
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
width="35" height="35"
viewBox="0 0 172 172"
style=" fill:#000000;"><defs><linearGradient x1="99.4375" y1="43.33594" x2="99.4375" y2="60.14625" gradientUnits="userSpaceOnUse" id="color-1_43971_gr1"><stop offset="0" stop-color="#4ec9ff"></stop><stop offset="1" stop-color="#2bffe6"></stop></linearGradient><linearGradient x1="106.15625" y1="26.875" x2="106.15625" y2="146.16775" gradientUnits="userSpaceOnUse" id="color-2_43971_gr2"><stop offset="0" stop-color="#009add"></stop><stop offset="1" stop-color="#00baa4"></stop></linearGradient><linearGradient x1="83.3125" y1="26.875" x2="83.3125" y2="146.16775" gradientUnits="userSpaceOnUse" id="color-3_43971_gr3"><stop offset="0" stop-color="#009add"></stop><stop offset="1" stop-color="#00baa4"></stop></linearGradient><linearGradient x1="73.90625" y1="26.875" x2="73.90625" y2="146.16775" gradientUnits="userSpaceOnUse" id="color-4_43971_gr4"><stop offset="0" stop-color="#009add"></stop><stop offset="1" stop-color="#00baa4"></stop></linearGradient><linearGradient x1="51.0625" y1="26.875" x2="51.0625" y2="146.16775" gradientUnits="userSpaceOnUse" id="color-5_43971_gr5"><stop offset="0" stop-color="#009add"></stop><stop offset="1" stop-color="#00baa4"></stop></linearGradient><linearGradient x1="51.0625" y1="26.875" x2="51.0625" y2="146.16775" gradientUnits="userSpaceOnUse" id="color-6_43971_gr6"><stop offset="0" stop-color="#009add"></stop><stop offset="1" stop-color="#00baa4"></stop></linearGradient><linearGradient x1="45.6875" y1="26.875" x2="45.6875" y2="146.16775" gradientUnits="userSpaceOnUse" id="color-7_43971_gr7"><stop offset="0" stop-color="#009add"></stop><stop offset="1" stop-color="#00baa4"></stop></linearGradient><linearGradient x1="43" y1="26.875" x2="43" y2="146.16775" gradientUnits="userSpaceOnUse" id="color-8_43971_gr8"><stop offset="0" stop-color="#009add"></stop><stop offset="1" stop-color="#00baa4"></stop></linearGradient></defs><g fill="none" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><path d="M0,172v-172h172v172z" fill="none"></path><g><path d="M112.875,59.125h-26.875c-1.4835,0 -2.6875,-1.204 -2.6875,-2.6875v-10.75c0,-1.4835 1.204,-2.6875 2.6875,-2.6875h26.875c1.4835,0 2.6875,1.204 2.6875,2.6875v10.75c0,1.4835 -1.204,2.6875 -2.6875,2.6875z" fill="url(#color-1_43971_gr1)"></path><path d="M155.875,96.75c0,-7.97381 -5.82381,-14.59581 -13.4375,-15.88313v-18.82325c0,-2.08819 -1.16906,-3.94525 -3.05031,-4.85094c-1.88125,-0.90031 -4.06081,-0.65575 -5.69481,0.64769l-21.48925,17.18925c-0.08062,0.0645 -0.13975,0.14781 -0.21769,0.21769h-31.36044c-7.40944,0 -13.4375,6.02806 -13.4375,13.4375h-5.375c-2.96431,0 -5.375,2.41069 -5.375,5.375v5.375c0,2.96431 2.41069,5.375 5.375,5.375h5.375c0,7.40944 6.02806,13.4375 13.4375,13.4375v16.125c0,5.92863 4.82138,10.75 10.75,10.75c5.92863,0 10.75,-4.82137 10.75,-10.75v-16.125h9.86044c0.07794,0.06988 0.13706,0.15319 0.22038,0.22037l21.48656,17.18925c0.98094,0.78475 2.16075,1.18519 3.35131,1.18519c0.79281,0 1.59369,-0.17738 2.3435,-0.5375c1.88125,-0.903 3.05031,-2.76275 3.05031,-4.84825v-18.82325c7.61369,-1.28731 13.4375,-7.90931 13.4375,-15.88312zM61.8125,99.4375v-5.375h5.375v5.375zM96.75,134.375c0,2.96431 -2.41069,5.375 -5.375,5.375c-2.96431,0 -5.375,-2.41069 -5.375,-5.375v-16.125h10.75zM80.625,112.875c-4.44513,0 -8.0625,-3.61738 -8.0625,-8.0625v-16.125c0,-4.44513 3.61737,-8.0625 8.0625,-8.0625h29.5625v32.25h-8.0625zM137.05175,131.46175l-21.48925,-17.19462v-35.04231l10.75,-8.59194v26.11713h5.375v-30.41175l5.375,-4.29462l0.00538,69.42887c0,0 -0.00538,-0.00269 -0.01613,-0.01075zM142.4375,107.11837v-20.73675c4.6225,1.20131 8.0625,5.375 8.0625,10.36838c0,4.99337 -3.44,9.16706 -8.0625,10.36838z" fill="url(#color-2_43971_gr2)"></path><path d="M77.9375,91.375v5.375h5.375v-5.375h5.375v-5.375h-5.375c-2.96431,0 -5.375,2.41069 -5.375,5.375z" fill="url(#color-3_43971_gr3)"></path><path d="M21.5,107.5v-67.1875c0,-4.44512 3.61737,-8.0625 8.0625,-8.0625h88.6875c4.44512,0 8.0625,3.61738 8.0625,8.0625v10.75h5.375v-10.75c0,-7.40944 -6.02806,-13.4375 -13.4375,-13.4375h-88.6875c-7.40944,0 -13.4375,6.02806 -13.4375,13.4375v67.1875c0,7.40944 6.02806,13.4375 13.4375,13.4375h32.25v-5.375h-32.25c-4.44513,0 -8.0625,-3.61737 -8.0625,-8.0625z" fill="url(#color-4_43971_gr4)"></path><path d="M32.25,43h37.625v5.375h-37.625z" fill="url(#color-5_43971_gr5)"></path><path d="M32.25,53.75h37.625v5.375h-37.625z" fill="url(#color-6_43971_gr6)"></path><path d="M32.25,64.5h26.875v5.375h-26.875z" fill="url(#color-7_43971_gr7)"></path><path d="M32.25,75.25h21.5v5.375h-21.5z" fill="url(#color-8_43971_gr8)"></path></g></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="35" height="35" viewBox="0 0 172 172">
<defs>
<linearGradient id="g1" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#4ec9ff"/>
<stop offset="100%" stop-color="#2bffe6"/>
</linearGradient>
<linearGradient id="g2" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#009add"/>
<stop offset="100%" stop-color="#00baa4"/>
</linearGradient>
</defs>
<!-- Chat bubble -->
<rect x="20" y="28" rx="10" ry="10" width="110" height="78" fill="url(#g2)"/>
<polygon points="50,106 65,106 55,126" fill="url(#g2)"/>
<!-- Prompt lines -->
<rect x="35" y="45" width="70" height="8" rx="4" fill="url(#g1)"/>
<rect x="35" y="60" width="55" height="8" rx="4" fill="url(#g1)"/>
<rect x="35" y="75" width="40" height="8" rx="4" fill="url(#g1)"/>
<!-- AI Spark -->
<polygon points="115,40 120,55 135,60 120,65 115,80 110,65 95,60 110,55"
fill="url(#g1)"/>
</svg>
</div>
<div class="col">
<div class="fs-12 m-t-5 all-caps m-b-5">AI Prompts</div>
@@ -122,11 +122,13 @@
<div class="col">
<div class="row">
<div class="col">
<list-component key="lock-1" section="lockPaidBillGroup" :endpoint="route('api.setting.list.lock')" :options="{'key_value_pair_in': ['UI_SUPPLIER_PAID_CURRENCY_ORDER_TAB_IS_LOCKED']}" style="min-height: 50px;width:100%">
<!-- cief todo: 110 - Prototype Period Lock - Starts -->
<!-- <list-component key="lock-1" section="lockPaidBillGroup" :endpoint="route('api.setting.list.lock')" :options="{'key_value_pair_in': ['UI_SUPPLIER_PAID_CURRENCY_ORDER_TAB_IS_LOCKED']}" style="min-height: 50px;width:100%">
<template slot="list" slot-scope="{data}">
<component-lock section="lockPaidBillGroup" :data="data"></component-lock>
</template>
</list-component>
</list-component> -->
<!-- cief todo: 110 - Prototype Period Lock - Ends -->
<bill-group-list-section-component section="paidBillGroupList"></bill-group-list-section-component>
</div>
</div>
+4
View File
@@ -82,6 +82,10 @@ Route::group(['middleware' => 'api', 'prefix' => 'v1', 'as' => 'api.'], function
require __DIR__ . '/key_value_pair.php';
require __DIR__ . '/setting.php';
require __DIR__ . '/affiliate.php';
// require __DIR__ . '/rate.php';
// require __DIR__ . '/receipt.php';
});
+2
View File
@@ -6,6 +6,8 @@ use App\Http\Controllers\Bookings\UpdateBookingAmountController;
use App\Http\Controllers\Bookings\CreateBookingLockController;
use App\Http\Controllers\Bookings\DeleteBookingLockController;
use App\Http\Controllers\Bookings\CreateBankingInvoiceTransactionController;
use App\Http\Controllers\Bookings\CreateBookingLockController;
use App\Http\Controllers\Bookings\DeleteBookingLockController;
use Illuminate\Support\Facades\Route;
Route::group(['prefix' => 'booking', 'as' => 'booking.', 'namespace' => 'Bookings'], function () {
+2
View File
@@ -12,4 +12,6 @@ Route::prefix('rule')
Route::post('/check/tranfer/period-lock', [CheckRuleController::class, 'checkTransferPeriodLockRule'])->name('check.transfer.period.lock');
Route::post('/check/e-invoice/amount-limit', [CheckRuleController::class, 'checkEInvoiceAmountLimitRule'])->name('check.einvoice.amount-limit');
Route::post('/check/tranfer/period-lock', [CheckRuleController::class, 'checkTransferPeriodLockRule'])->name('check.transfer.period.lock');
});
+3 -3
View File
@@ -1,8 +1,8 @@
<?php
use App\Http\Controllers\Settings\CreateLockController;
use App\Http\Controllers\Settings\ListLocksController;
use App\Http\Controllers\Settings\UpdateLockController;
use App\Http\Controllers\KeyValuePairs\CreateLockController;
use App\Http\Controllers\KeyValuePairs\ListLocksController;
use App\Http\Controllers\KeyValuePairs\UpdateLockController;
use Illuminate\Support\Facades\Route;
Route::prefix('setting')
+16
View File
@@ -1406,3 +1406,19 @@ Route::get('/run-batch-unfinished-payment-orders', function (Request $request) {
Route::get('/locks', function () {
return view('pages.dashboards.admin_lock');
})->name('admin.admin_lock');
// Landing Pages
$landingPages = [
'1688-payment-alternative-cn',
'en-1688-vip-landing-page-general-fb',
'en-1688-vip-landing-page-general-google',
'1688-vip-payment-landing-page-wf-comparison-fb',
'1688-vip-payment-landing-page-general-fb',
'1688-vip-payment-landing-page-wf-comparison-google',
'1688-vip-payment-landing-page-general-google',
];
foreach ($landingPages as $landingPage) {
Route::get('/'.$landingPage, function () use ($landingPage) {
return view('pages.landing.'.$landingPage);
})->name('landing.'.$landingPage);
}