Compare commits

..

58 Commits

Author SHA1 Message Date
5e98841eea Update app/Models/Ecommerce/Product/Category/Category.php 2026-03-04 23:28:31 +05:00
2b8f9aa314 wip 2026-03-02 07:30:59 +05:00
cb63c54c39 wip 2026-03-02 07:08:57 +05:00
b7bc192e6f wip 2026-03-02 07:01:14 +05:00
06617a0005 wip 2026-02-25 19:24:49 +05:00
da2645fae9 add provinces seeder 2026-02-25 19:07:35 +05:00
066f4d6a53 ignore data dir in db 2026-02-25 19:04:00 +05:00
Mekan1206
1e84ceab3c Refactor code for consistency and clarity; update seeder comments, enhance error handling, and improve API routes. Added 'original' field to ProductMediaResource and adjusted various formatting issues across multiple files. 2026-02-20 15:33:29 +05:00
Mekan1206
a8599d9c79 WIP 2026-02-19 18:11:13 +05:00
Mekan1206
78ef14b99b WIP 2026-02-19 17:57:01 +05:00
Mekan1206
1a63c52106 WIP 2026-02-19 17:55:45 +05:00
Mekan1206
75a6af68eb WIP 2026-02-19 17:49:32 +05:00
Mekan1206
58c1915413 image 2026-02-19 06:22:37 +05:00
Mekan1206
ba537b7868 WIP 2026-02-19 01:08:52 +05:00
Mekan1206
bf69d6733b WIP 2026-02-19 00:47:22 +05:00
Mekan1206
9107d3118d WIP 2026-02-19 00:38:32 +05:00
Mekan1206
fac624b2a5 WIP 2026-02-19 00:35:01 +05:00
Mekan1206
9071c9a4c6 WIP 2026-02-18 23:38:01 +05:00
Mekan1206
18e510674a WIP 2026-02-18 23:37:02 +05:00
Mekan1206
073bbd497b only 400, 800, 1200 image resolutions remained 2026-02-18 23:32:00 +05:00
Mekan1206
ab3e69e831 WIP 2026-02-18 04:23:36 +05:00
Mekan1206
18401b908f WIP 2026-02-18 04:20:05 +05:00
Mekan1206
c712fa07ba WIP 2026-02-18 04:06:40 +05:00
Mekan1206
f011da72d9 WIP 2026-02-18 04:01:28 +05:00
Mekan1206
4a0e24683a WIP 2026-02-15 00:31:16 +05:00
Mekan1206
49ef491e80 WIP 2026-02-14 23:09:52 +05:00
Mekan1206
1880a167b3 Update DatabaseSeeder to include all seeders and add inventory creation in UsersTableSeeder
- Enabled all previously commented-out seeders in DatabaseSeeder for comprehensive data seeding.
- Added inventory creation logic in UsersTableSeeder to initialize a new inventory record for 'Tmpost'.
2026-02-14 00:38:15 +05:00
Mekan1206
ec33006984 Update DatabaseSeeder to include MediaSeeder and enhance 404 error page localization
- Added MediaSeeder to DatabaseSeeder for improved data seeding.
- Updated 404 error page to use localized string for "Page not found" and added links for navigation.
- Added new translation for "Page not found" in tk.json.
2026-02-13 22:51:43 +05:00
Mekan1206
147e7b9516 Update DatabaseSeeder to include MediaSeeder and enhance 404 error page localization
- Added MediaSeeder to DatabaseSeeder for improved data seeding.
- Updated lang/tk.json to include a new translation for "Page not found".
- Refactored 404 error page to utilize localization for the title and home link.
2026-02-11 04:30:32 +05:00
Mekan1206
e70ec773f9 Comment out ProductStocksSeeder in DatabaseSeeder and implement stock updates in ProductStocksSeeder
- Commented out the ProductStocksSeeder in DatabaseSeeder for future adjustments.
- Implemented stock updates in ProductStocksSeeder to update product stock and inventory based on data from stocks.json.
- Enhanced transaction handling and ensured proper sequence setting for inventory_product table.
2026-02-11 03:42:54 +05:00
Mekan1206
e2adf5e9da write me a warner 2026-02-11 03:15:43 +05:00
Mekan1206
d3ac6ff8d9 Comment out ProductPropertyValuesSeeder in DatabaseSeeder for future adjustments 2026-02-11 02:50:49 +05:00
Mekan1206
b0c6a4236c Refactor seeders for improved clarity and functionality
- Reorganized imports in DatabaseSeeder for better structure.
- Enabled ProductCategoryRelationshipsSeeder and ProductBarcodesSeeder in DatabaseSeeder.
- Updated ProductPropertyValuesSeeder to enhance property value handling and added a new method for filling product property values.
- Removed unused imports from ProductBarcodesSeeder, ProductCategoryRelationshipsSeeder, and ProductPropertiesSeeder.
- Ensured consistent formatting by adding missing newlines at the end of files.
2026-02-11 00:59:13 +05:00
Mekan1206
9fac84a882 Enhance product handling and seeding logic
- Added a call to sync properties JSON in UpdateProductRelations job if the method exists.
- Updated ProductFieldsForDetail to provide a default value of '-' for missing property values.
- Simplified the insertion logic in ProductPropertyValuesSeeder by replacing 'tm' with 'tk' in the value field and removed commented-out code for clarity.
2026-02-09 23:15:56 +05:00
Mekan1206
8f49fe0124 404 add animation 2026-02-09 22:41:53 +05:00
Mekan1206
43272bb1b1 nice 404 page 2026-02-09 22:28:57 +05:00
Mekan1206
c48ad83548 Update DatabaseSeeder to include additional seeders and comment out FavoritesSeeder
- Added ProductCategoryRelationshipsSeeder, ProductBarcodesSeeder, SectionsSeeder, ProductPropertiesSeeder, and ProductPropertyValuesSeeder to DatabaseSeeder.
- Commented out FavoritesSeeder and SectionsSeeder for future adjustments.
2026-02-09 03:29:21 +05:00
Mekan1206
b4a05e3f8c Add FavoritesSeeder to DatabaseSeeder for data population 2026-02-09 02:32:52 +05:00
Mekan1206
bac1579285 Remove unused MorphToMany relationships from models and add CategoriesTableSeeder for category data population 2026-02-09 02:26:59 +05:00
Mekan1206
41d6ddc346 Update DatabaseSeeder to include CategoriesTableSeeder and adjust product seeders
- Added CategoriesTableSeeder to the run method in DatabaseSeeder.
- Commented out ProductsTableSeeder and ProductPricesSeeder for future adjustments.
2026-02-09 00:59:04 +05:00
Mekan1206
522ebdae34 Refactor product relations to use new category_product and channel_product tables
- Updated queries and relationships in various controllers and models to replace `product_has_relations` with `category_product` and `channel_product`.
- Adjusted methods in `ProductFilterer`, `FilterParamsController`, and `FilterController` to reflect the new database structure.
- Modified seeder to insert data into the new `channel_product` table.
- Updated tests to ensure compatibility with the new product relation structure.
2026-02-09 00:48:22 +05:00
Mekan1206
683fa5e0d9 Refactor helper functions and update seeders
- Simplified `tmpostChannel` and `tmpostDefaultInventory` functions by removing caching logic.
- Changed return type of `namesWithTaxes` method in `CategoryRepository` to `mixed`.
- Enabled `ProductsTableSeeder` and added user association logic for product relations.
- Updated `BrandsSeeder` to include the product ID in the slug.
- Added `old_customer_id` to `options` in `SellersTableSeeder` for user tracking.
2026-02-08 23:12:40 +05:00
Mekan1206
d83bc03258 WIP 2026-02-08 22:08:53 +05:00
Mekan1206
de1d7fbed8 wip 2026-02-08 21:34:32 +05:00
Mekan1206
d3156e228f seed sellers and warehouses 2026-02-08 21:26:06 +05:00
Mekan1206
299abeecbf needed 2026-02-08 20:32:40 +05:00
Mekan1206
201e112085 needed 2026-02-08 20:32:33 +05:00
Mekan1206
30a94b3533 WIP 2026-02-08 17:39:46 +05:00
Mekan1206
0d4499b131 WIP 2026-02-08 17:35:21 +05:00
Mekan1206
d3a528d264 WIP 2026-02-08 17:02:22 +05:00
Mekan1206
5337d2a804 WIP 2026-02-08 16:59:35 +05:00
Mekan1206
c46eccb24f Refactor code for improved readability and consistency
- Removed unnecessary blank lines in various files to enhance code clarity.
- Updated comments for consistency and clarity across multiple classes and methods.
- Adjusted spacing in test files for better formatting and readability.
2026-02-08 02:24:43 +05:00
Mekan1206
2dfa3747b5 WIP 2026-02-08 02:07:05 +05:00
Mekan1206
25359c6b6e WIP 2026-02-08 02:04:01 +05:00
Mekan1206
968c9ed42a Add product view tracking and related functionality
- Implemented product view tracking in ProductController to log user views.
- Added a relationship for viewed products in the User model.
- Introduced a method in ProductRepository to filter products viewed by a user.
- Updated API routes to include endpoint for retrieving viewed products.
- Commented out SMS notification logic in SendOrderCreatedNotification.
- Removed CreateOrderServiceTest as it is no longer needed.
2026-02-08 02:02:30 +05:00
dee6b0df56 wip 2026-02-05 18:09:47 +05:00
ace4442879 wip 2026-02-05 17:54:24 +05:00
eaae8b9be9 Refactor order creation logic by introducing CreateOrderService and removing the create method from OrderRepository. Update ProductRepository with stricter type declarations and fix minor typos in comments. 2026-02-05 01:29:10 +05:00
182 changed files with 2481 additions and 1290955 deletions

View File

@@ -7,6 +7,8 @@ APP_URL=http://localhost
API_TOKEN=123
NOVA_LICENSE_KEY=UEkhFwqhhYw2UPqcoVNWWhKrZOOWXujgj7pLPdDzMqflYX4Pwl
DEBUGBAR_ENABLED=false
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug

View File

@@ -5,7 +5,7 @@
# Install posgres and configure
sudo su - postgres
psql
CREATE USER postshop WITH PASSWORD 'ACvL2(F@H^F)D7gs';
CREATE USER postshop WITH PASSWORD 'HRbuBNRBaTPeUfbcFf9XHWay';
CREATE DATABASE postshopdb WITH OWNER = postshop LC_COLLATE = 'en_US.UTF-8' TEMPLATE template0;
# Clone

View File

@@ -31,7 +31,7 @@ class SyncProductPropertiesJson extends Command
// Using cursor to be memory efficient
$products = Product::cursor();
$count = Product::count();
$bar = $this->output->createProgressBar($count);
$bar->start();

View File

@@ -18,6 +18,9 @@ class Kernel extends ConsoleKernel
// Remove non saved attachments...
$schedule->call(new PruneStaleAttachments)->daily();
// IF any warnings unresolved warnings exists, send notify me
$schedule->call(new WarnDev)->dailyAt('16:00');
}
/**

25
app/Console/WarnDev.php Normal file
View File

@@ -0,0 +1,25 @@
<?php
namespace App\Console;
use App\Models\System\Warning;
use Illuminate\Console\Command;
class WarnDev extends Command
{
/**
* Notify me if any unresolved warnings exists
*
* @return void
*/
public function __invoke()
{
$warnings = Warning::whereNull('resolved_at')->get();
if ($warnings->isEmpty()) {
return;
}
sendSMS('61929248', 'Warnings: '.$warnings->count());
}
}

View File

@@ -3,7 +3,9 @@
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Throwable;
class Handler extends ExceptionHandler
{
@@ -29,5 +31,25 @@ class Handler extends ExceptionHandler
return response()->noContent(404);
}
});
$this->reportable(function (Throwable $e) {
$statusCode = $e instanceof HttpException ? $e->getStatusCode() : 500;
// only real server errors
if ($statusCode < 500) {
return;
}
try {
warn(
message: get_class($e),
content: $e->getMessage(),
where: $e->getFile().':'.$e->getLine(),
notes: substr($e->getTraceAsString(), 0, 65000),
);
} catch (Throwable $ignored) {
// logging must never crash the app
}
});
}
}

View File

@@ -64,7 +64,7 @@ class ProductFilterer
if ($this->request->filled('properties')) {
foreach ($this->request->input('properties') as $attributeSlug => $values) {
$valuesArray = explode(',', $values);
$this->queryBuilder->where(function ($query) use ($attributeSlug, $valuesArray) {
foreach ($valuesArray as $value) {
$query->orWhereJsonContains("properties_json->{$attributeSlug}", $value);
@@ -81,11 +81,10 @@ class ProductFilterer
$this->queryBuilder->whereIn(
column: 'id',
values: (
fn ($query) => $query->from('product_has_relations')
fn ($query) => $query->from('category_product')
->select('product_id')
->distinct('product_id')
->where('productable_type', '=', 'category')
->whereIn('productable_id', explode(',', $this->request->categories))
->whereIn('category_id', explode(',', $this->request->categories))
)
);
}

View File

@@ -3,6 +3,7 @@
use App\Models\Auth\Verification;
use App\Models\Ecommerce\Channel\Channel;
use App\Models\Ecommerce\Product\Inventory\Inventory;
use App\Models\System\Warning;
use App\Repositories\Ecommerce\Product\Barcode\BarcodeRepository;
use Illuminate\Http\Client\PendingRequest;
use Illuminate\Support\Collection;
@@ -73,8 +74,6 @@ if (! function_exists('sendSMS')) {
return [];
}
return [];
$response = Http::withToken('WsTEJTBGlQiJ')
->retry(
times: 3,
@@ -178,9 +177,7 @@ if (! function_exists('tmpostChannel')) {
*/
function tmpostChannel(): Channel
{
Cache::rememberForever('tmpostChannel', fn () => Channel::tmpostDefault());
return Cache::get('tmpostChannel');
return Channel::tmpostDefault();
}
}
@@ -190,9 +187,7 @@ if (! function_exists('tmpostDefaultInventory')) {
*/
function tmpostDefaultInventory(): mixed
{
Cache::rememberForever('tmpostDefaultInventory', fn () => Inventory::tmpostDefault());
return Cache::get('tmpostDefaultInventory');
return Inventory::tmpostDefault();
}
}
@@ -394,3 +389,16 @@ function createHalkbankOrder($price = 123): array
'url' => $paymentResponse['formUrl'],
];
}
/**
* Warn brother
*/
function warn(string $message, string $content = '', string $where = '', string $notes = ''): void
{
Warning::forceCreate([
'name' => $message,
'content' => $content,
'where' => $where,
'notes' => $notes,
]);
}

View File

@@ -11,7 +11,7 @@ class AppVersionController extends Controller
{
/**
* Check for app updates
*
*
* This api should be triggered when the app is **launched**, and **current version** and **operating system** should be sent in body. It should check if there is any update available for the app.\
* **Handle Response**:\
* * **Update Required**: If the update is critical/mandatory, show a **blocking modal**. The user cannot dismiss it and must click a button to go to the App Store or Google Play Store.\

View File

@@ -14,17 +14,17 @@ class AuthRegisterRequest extends FormRequest
public function rules(): array
{
return [
/**
/**
* @example 61929248
*/
'phone_number' => ['required', 'integer', 'between:61000000,71999999', 'unique:users,phone_number'],
/**
/**
* @example Nurmuhammet Allanov
*/
'name' => ['required', 'string', 'max:255'],
/**
/**
* @example 75 3rd Ave, New York, NY 10003, USA
*/
'address' => ['required', 'string', 'max:255'],

View File

@@ -15,7 +15,7 @@ class AuthController extends Controller
{
/**
* Guest token (walk-in-user)
*
*
* Use when user visits website/app for the first time, and save the token in cache.
*/
public function guestToken(): JsonResponse
@@ -28,8 +28,8 @@ class AuthController extends Controller
/**
* Register user
*
* Register a new user and send a verification code to their phone number. Then make another request to verification route.
*
* Register a new user and send a verification code to their phone number. Then make another request to verification route.
*/
public function register(AuthRegisterRequest $request): JsonResponse
{
@@ -46,7 +46,7 @@ class AuthController extends Controller
/**
* Login
*
*
* Send a verification code to the phone number. Then make another request to verify route.
*/
public function login(AuthLoginRequest $request): JsonResponse
@@ -62,7 +62,7 @@ class AuthController extends Controller
/**
* Verify the code
*
*
* After verification, bearer token will be returned.
*/
public function verify(AuthVerifyRequest $request): JsonResponse

View File

@@ -15,9 +15,8 @@ class BrandMediaResource extends JsonResource
public function toArray(Request $request): array
{
return [
'thumbnail' => $this->getUrl('thumb200x200'),
'thumbnail' => $this->getUrl('thumb400x400'),
'images_400x400' => $this->getUrl('thumb400x400'),
'images_720x720' => $this->getUrl('thumb720x720'),
'images_800x800' => $this->getUrl('thumb800x800'),
'images_1200x1200' => $this->getUrl('thumb1200x1200'),
];

View File

@@ -55,7 +55,7 @@ class CategoryController extends Controller
}
/**
* Brands (products)
* Categories (products)
*/
public function products(BasicProductIndexRequest $request, Category $category): JsonResponse
{

View File

@@ -17,7 +17,6 @@ class CategoryMediaResource extends JsonResource
return [
'thumbnail' => $this->getUrl(),
'images_400x400' => $this->getUrl('thumb400x400'),
'images_720x720' => $this->getUrl('thumb720x720'),
'images_800x800' => $this->getUrl('thumb800x800'),
'images_1200x1200' => $this->getUrl('thumb1200x1200'),
];

View File

@@ -0,0 +1,25 @@
<?php
namespace App\Http\Controllers\Api\V1\Category\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class SelectedCategoryResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'description' => $this->description,
'is_visible' => $this->is_visible,
'categories' => CategoryResource::collection($this->whenLoaded('categories')),
];
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace App\Http\Controllers\Api\V1\Category;
use App\Http\Controllers\Api\V1\Category\Resources\SelectedCategoryResource;
use App\Http\Controllers\Controller;
use App\Models\Ecommerce\Product\Category\SelectedCategory;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class SelectedCategoryController extends Controller
{
/**
* Selected Categories (index)
*/
public function index(Request $request): JsonResponse
{
$selectedCategories = SelectedCategory::query()
->where('is_visible', true)
->with(['categories' => function ($query) {
$query->where('is_visible', true)->ordered()->with(['media']);
}])
->get();
return response()->json(SelectedCategoryResource::collection($selectedCategories));
}
/**
* Selected Categories (show)
*/
public function show(SelectedCategory $selectedCategory): JsonResponse
{
$selectedCategory->load('categories');
return response()->json(new SelectedCategoryResource($selectedCategory));
}
}

View File

@@ -38,10 +38,9 @@ class FilterParamsController extends Controller
$category_id = (int) $request->category_id;
$brand_ids = DB::table('products')
->join('product_has_relations', function ($join) use ($category_id) {
$join->on('products.id', '=', 'product_has_relations.product_id')
->where('product_has_relations.productable_id', '=', $category_id)
->where('product_has_relations.productable_type', '=', 'category');
->join('category_product', function ($join) use ($category_id) {
$join->on('products.id', '=', 'category_product.product_id')
->where('category_product.category_id', '=', $category_id);
})
->select(['id', 'brand_id'])
->pluck('brand_id');

View File

@@ -97,9 +97,8 @@ class FilterController extends Controller
->distinct('products.id')
->pluck('products.id');
return Category::where('is_visible', true)->ordered()->join('product_has_relations', 'categories.id', '=', 'product_has_relations.productable_id')
->where('product_has_relations.productable_type', '=', 'category')
->whereIntegerInRaw('product_has_relations.product_id', $products)
return Category::where('is_visible', true)->ordered()->join('category_product', 'categories.id', '=', 'category_product.category_id')
->whereIntegerInRaw('category_product.product_id', $products)
->get(['id', 'parent_id', 'name'])
->unique('categories.id');
}

View File

@@ -87,9 +87,8 @@ class CategoriesFilter
->distinct('products.id')
->pluck('products.id');
return $this->queryBuilder->join('product_has_relations', 'categories.id', '=', 'product_has_relations.productable_id')
->where('product_has_relations.productable_type', '=', 'category')
->whereIntegerInRaw('product_has_relations.product_id', $products)
return $this->queryBuilder->join('category_product', 'categories.id', '=', 'category_product.category_id')
->whereIntegerInRaw('category_product.product_id', $products)
->get($this->columns)
->unique('categories.id');
}

View File

@@ -14,7 +14,7 @@ class OrderPaymentController extends Controller
public function index(): JsonResponse
{
return response()->rest(
PaymentType::all(['id', 'name'])
PaymentType::query()->where('is_enabled', true)->get(['id', 'name'])
->map(fn ($paymentType) => [
'id' => $paymentType->id,
'name' => $paymentType->name,

View File

@@ -6,7 +6,9 @@ use App\Http\Controllers\Controller;
use App\Http\Requests\CheckoutOrderRequest;
use App\Http\Resources\Api\V1\Order\OrderIndexResource;
use App\Models\Ecommerce\Product\Order\Order;
use App\Models\Ecommerce\Product\Order\Shipping\OrderShipping;
use App\Repositories\Ecommerce\Order\OrderRepository;
use App\Services\Order\CreateOrderService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -32,12 +34,33 @@ class OrderController extends Controller
return response()->rest(OrderRepository::availableTimes());
}
/**
* Order deliveries
*/
public function deliveries(): JsonResponse
{
return response()->rest([
[
'name' => OrderShipping::STANDART,
'price' => 20,
],
[
'name' => OrderShipping::SELF_PICKUP,
'price' => 0
],
[
'name' => OrderShipping::REGION,
'price' => 40,
],
]);
}
/**
* (*) Store order
*/
public function store(CheckoutOrderRequest $request): JsonResponse
public function store(CheckoutOrderRequest $request, CreateOrderService $service): JsonResponse
{
$order = (new OrderRepository($request->all()))->create();
$order = $service->execute(auth()->user(), $request->all());
$url = null;
if ($request->payment_type_id == 3) {
@@ -80,7 +103,6 @@ class OrderController extends Controller
/**
* Remove the specified resource from storage.
*
* @param Order $order
* @return \Illuminate\Http\Response
*/
public function destroy(Order $order)

View File

@@ -7,6 +7,7 @@ use App\Http\Controllers\Api\V1\Product\Resources\ProductShowResource;
use App\Http\Controllers\Controller;
use App\Http\Requests\Api\V1\Product\ProductIndexRequest;
use App\Models\Ecommerce\Product\Product\Product;
use App\Models\Ecommerce\Product\ProductView\ProductView;
use App\Repositories\Ecommerce\Product\ProductRepository;
use Illuminate\Http\JsonResponse;
@@ -33,6 +34,15 @@ class ProductController extends Controller
*/
public function show(Product $product): JsonResponse
{
if (auth('sanctum')->check()) {
ProductView::updateOrCreate([
'user_id' => auth('sanctum')->id(),
'product_id' => $product->id,
], [
'updated_at' => now(),
]);
}
$product->load([
'channels:id,name',
'properties',

View File

@@ -16,18 +16,17 @@ class ProductRelatedController extends Controller
*/
public function index(Product $product): JsonResponse
{
$products = DB::table('product_has_relations')
->select('product_has_relations.product_id')
->whereIn('product_has_relations.productable_id', (function ($query) use ($product) {
$query->from('product_has_relations')
->select('productable_id')
->distinct('productable_id')
->where('productable_type', '=', 'category')
$products = DB::table('category_product')
->select('category_product.product_id')
->whereIn('category_product.category_id', (function ($query) use ($product) {
$query->from('category_product')
->select('category_id')
->distinct('category_id')
->where('product_id', '=', $product->id);
}))
->limit(12)
->orderByRaw('RANDOM()')
->pluck('product_has_relations.product_id')
->pluck('category_product.product_id')
->unique();
return response()->rest(

View File

@@ -4,7 +4,6 @@ namespace App\Http\Controllers\Api\V1\Product\Resources;
use App\Http\Resources\MediaResource;
use App\Repositories\Ecommerce\Product\Property\PropertyRepository;
use App\Http\Controllers\Api\V1\Product\Resources\Variant\ProductVariantResource;
use Illuminate\Http\Resources\Json\JsonResource;
class ProductIndexResource extends JsonResource

View File

@@ -15,9 +15,9 @@ class ProductMediaResource extends JsonResource
public function toArray(Request $request): array
{
return [
'thumbnail' => $this->getUrl('thumb288x431'),
'original' => $this->getUrl(),
'thumbnail' => $this->getUrl('thumb400x400'),
'images_400x400' => $this->getUrl('thumb400x400'),
'images_720x720' => $this->getUrl('thumb720x720'),
'images_800x800' => $this->getUrl('thumb800x800'),
'images_1200x1200' => $this->getUrl('thumb1200x1200'),
];

View File

@@ -0,0 +1,27 @@
<?php
namespace App\Http\Controllers\Api\V1\Product;
use App\Http\Controllers\Api\V1\Product\Resources\ProductIndexResource;
use App\Http\Controllers\Controller;
use App\Repositories\Ecommerce\Product\ProductRepository;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ViewedProductController extends Controller
{
/**
* Viewed Products (index)
*/
public function index(Request $request): JsonResponse
{
return response()->rest_paginate(
ProductIndexResource::collection(
ProductRepository::make($request)
->applyBasicQueries()
->applyViewedBy(auth('sanctum')->user())
->simplePaginate()
)
);
}
}

View File

@@ -10,7 +10,7 @@ class CheckForUpdateRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array|string>
*/
public function rules(): array

View File

@@ -2,7 +2,6 @@
namespace App\Http\Requests\Api\V1\Auth;
use App\Rules\VerificationRule;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

View File

@@ -15,12 +15,12 @@ class AuthVerifyRequest extends FormRequest
public function rules(): array
{
return [
/**
/**
* @example 61929248
*/
'phone_number' => ['required', 'integer', 'between:61000000,65999999'],
/**
/**
* @example 99934
*/
'code' => ['required', 'integer', new VerificationRule($this->phone_number)],

View File

@@ -40,6 +40,7 @@ class CheckoutOrderRequest extends FormRequest
'customer_address' => ['required', 'string', 'max:255'],
'shipping_method' => ['required', 'string', 'max:255', Rule::in(array_keys(OrderShipping::values()))],
'shipping_price' => ['nullable', 'numeric'],
'payment_type_id' => ['required', Rule::in(array_keys(OrderPayment::values()))],
'notes' => ['nullable', 'string', 'max:255'],
@@ -65,7 +66,7 @@ class CheckoutOrderRequest extends FormRequest
'user_id' => auth()->id(),
'notes' => $this->notes ?: null,
'province_id' => $this->province_id ?: null,
'shipping_price' => OrderShipping::priceFor($this->shipping_method),
'shipping_price' => $this->shipping_price ?: OrderShipping::priceFor($this->shipping_method),
'delivery_time' => $this->delivery_time ?: OrderShipping::MORNING,
'delivery_at' => $this->delivery_at ?: date('Y-m-d'),
'source' => $this->source ?: OS::MOBILE_APP,

View File

@@ -17,7 +17,6 @@ class ChannelMediaResource extends JsonResource
return [
'thumbnail' => $this->getUrl(),
'images_400x400' => $this->getUrl('thumb400x400'),
'images_720x720' => $this->getUrl('thumb720x720'),
'images_800x800' => $this->getUrl('thumb800x800'),
'images_1200x1200' => $this->getUrl('thumb1200x1200'),
];

View File

@@ -15,9 +15,8 @@ class MediaResource extends JsonResource
public function toArray(Request $request): array
{
return [
'thumbnail' => $this->getUrl('thumb720x720'),
'thumbnail' => $this->getUrl('thumb400x400'),
'images_400x400' => $this->getUrl('thumb400x400'),
'images_720x720' => $this->getUrl('thumb720x720'),
'images_800x800' => $this->getUrl('thumb800x800'),
'images_1200x1200' => $this->getUrl('thumb1200x1200'),
];

View File

@@ -59,6 +59,11 @@ class UpdateProductRelations implements ShouldQueue
'product_custom_value' => in_array($attribute->type, ['text', 'number']) ? $this->properties[$attribute->slug] : null,
]);
});
// sync properties json
if (method_exists($this->model, 'syncPropertiesJson')) {
$this->model->syncPropertiesJson();
}
});
}
}

View File

@@ -31,9 +31,9 @@ class SendOrderCreatedNotification implements ShouldQueue
return;
}
$this->sendSMSToClient($event->order);
$this->sendSMSToStaff($event->order);
$this->sendSMSToVendors($event->order);
// $this->sendSMSToClient($event->order);
// $this->sendSMSToStaff($event->order);
// $this->sendSMSToVendors($event->order);
}
/**

View File

@@ -106,24 +106,15 @@ class Banner extends Model implements HasMedia
*/
public function registerMediaConversions(?Media $media = null): void
{
$this->addMediaConversion('thumb200x200')
->fit(Manipulations::FIT_CONTAIN, 200, 200);
$this->addMediaConversion('thumb400x400')
->fit(Manipulations::FIT_CONTAIN, 400, 400);
$this->addMediaConversion('thumb350x350')
->fit(Manipulations::FIT_CONTAIN, 350, 350);
$this->addMediaConversion('thumb720x720')
->fit(Manipulations::FIT_CONTAIN, 720, 720);
$this->addMediaConversion('thumb800x800')
->fit(Manipulations::FIT_CONTAIN, 800, 800);
$this->addMediaConversion('thumb1200x1200')
->fit(Manipulations::FIT_CONTAIN, 1200, 1200);
$this->addMediaConversion('thumb288x431')
->fit(Manipulations::FIT_CONTAIN, 288, 431);

View File

@@ -11,9 +11,9 @@ use App\Repositories\System\Cache\CacheRepository;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Laravel\Nova\Nova;
use Spatie\EloquentSortable\Sortable;
use Spatie\EloquentSortable\SortableTrait;
@@ -109,29 +109,14 @@ class Channel extends Model implements HasMedia, Sortable
*/
public function registerMediaConversions(?Media $media = null): void
{
$this->addMediaConversion('thumb150x150')
->fit(Manipulations::FIT_CONTAIN, 150, 150);
$this->addMediaConversion('thumb200x200')
->fit(Manipulations::FIT_CONTAIN, 200, 200);
$this->addMediaConversion('thumb400x400')
->fit(Manipulations::FIT_CONTAIN, 400, 400);
$this->addMediaConversion('thumb720x720')
->fit(Manipulations::FIT_CONTAIN, 720, 720);
$this->addMediaConversion('thumb800x800')
->fit(Manipulations::FIT_CONTAIN, 800, 800);
$this->addMediaConversion('thumb1200x1200')
->fit(Manipulations::FIT_CONTAIN, 1200, 1200);
$this->addMediaConversion('thumb288x431')
->fit(Manipulations::FIT_CONTAIN, 288, 431);
$this->addMediaConversion('thumb270x350')
->fit(Manipulations::FIT_CONTAIN, 270, 350);
}
/**
@@ -179,9 +164,9 @@ class Channel extends Model implements HasMedia, Sortable
/**
* Products
*/
public function products(): MorphToMany
public function products(): BelongsToMany
{
return $this->morphToMany(Product::class, 'productable', 'product_has_relations');
return $this->belongsToMany(Product::class, 'channel_product');
}
/**

View File

@@ -85,26 +85,14 @@ class Brand extends Model implements HasMedia, Sortable
*/
public function registerMediaConversions(?Media $media = null): void
{
$this->addMediaConversion('thumb200x200')
->fit(Manipulations::FIT_CONTAIN, 200, 200);
$this->addMediaConversion('thumb400x400')
->fit(Manipulations::FIT_CONTAIN, 400, 400);
$this->addMediaConversion('thumb720x720')
->fit(Manipulations::FIT_CONTAIN, 720, 720);
$this->addMediaConversion('thumb800x800')
->fit(Manipulations::FIT_CONTAIN, 800, 800);
$this->addMediaConversion('thumb1200x1200')
->fit(Manipulations::FIT_CONTAIN, 1200, 1200);
$this->addMediaConversion('thumb288x431')
->fit(Manipulations::FIT_CONTAIN, 288, 431);
$this->addMediaConversion('thumb270x350')
->fit(Manipulations::FIT_CONTAIN, 270, 350);
}
/**

View File

@@ -10,7 +10,6 @@ use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Spatie\EloquentSortable\Sortable;
use Spatie\EloquentSortable\SortableTrait;
use Spatie\Image\Manipulations;
@@ -83,7 +82,6 @@ class Category extends Model implements HasMedia, Sortable
{
$this->addMediaCollection('uploads')
->singleFile()
->acceptsMimeTypes(['image/jpg', 'image/jpeg', 'image/png'])
->useFallbackUrl(
sprintf('%s/logo-space.png', config('app.url'))
);
@@ -94,29 +92,14 @@ class Category extends Model implements HasMedia, Sortable
*/
public function registerMediaConversions(?Media $media = null): void
{
$this->addMediaConversion('thumb200x200')
->fit(Manipulations::FIT_CONTAIN, 200, 200);
$this->addMediaConversion('thumb400x400')
->fit(Manipulations::FIT_CONTAIN, 400, 400);
$this->addMediaConversion('thumb720x720')
->fit(Manipulations::FIT_CONTAIN, 720, 720);
$this->addMediaConversion('thumb800x800')
->fit(Manipulations::FIT_CONTAIN, 800, 800);
$this->addMediaConversion('thumb1200x1200')
->fit(Manipulations::FIT_CONTAIN, 1200, 1200);
$this->addMediaConversion('thumb288x431')
->fit(Manipulations::FIT_CONTAIN, 288, 431);
$this->addMediaConversion('thumb270x350')
->fit(Manipulations::FIT_CONTAIN, 270, 350);
$this->addMediaConversion('thumb657x230')
->fit(Manipulations::FIT_CROP, 657, 230);
}
/**
@@ -152,9 +135,9 @@ class Category extends Model implements HasMedia, Sortable
/**
* Category Products
*/
public function products(): MorphToMany
public function products(): BelongsToMany
{
return $this->morphToMany(Product::class, 'productable', 'product_has_relations');
return $this->belongsToMany(Product::class, 'category_product');
}
/**

View File

@@ -0,0 +1,31 @@
<?php
namespace App\Models\Ecommerce\Product\Category;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Spatie\Translatable\HasTranslations;
class SelectedCategory extends Model
{
use HasFactory;
use HasTranslations;
protected $fillable = [
'name',
'description',
'is_visible',
];
public $translatable = ['name', 'description'];
protected $casts = [
'is_visible' => 'boolean',
];
public function categories(): BelongsToMany
{
return $this->belongsToMany(Category::class, 'category_selected_category');
}
}

View File

@@ -5,7 +5,7 @@ namespace App\Models\Ecommerce\Product\Collection;
use App\Models\Ecommerce\Product\Product\Product;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Spatie\EloquentSortable\Sortable;
use Spatie\EloquentSortable\SortableTrait;
use Spatie\Image\Manipulations;
@@ -84,34 +84,22 @@ class Collection extends Model implements HasMedia, Sortable
*/
public function registerMediaConversions(?Media $media = null): void
{
$this->addMediaConversion('thumb200x200')
->fit(Manipulations::FIT_CONTAIN, 200, 200);
$this->addMediaConversion('thumb400x400')
->fit(Manipulations::FIT_CONTAIN, 400, 400);
$this->addMediaConversion('thumb720x720')
->fit(Manipulations::FIT_CONTAIN, 720, 720);
$this->addMediaConversion('thumb800x800')
->fit(Manipulations::FIT_CONTAIN, 800, 800);
$this->addMediaConversion('thumb1200x1200')
->fit(Manipulations::FIT_CONTAIN, 1200, 1200);
$this->addMediaConversion('thumb288x431')
->fit(Manipulations::FIT_CONTAIN, 288, 431);
$this->addMediaConversion('thumb270x350')
->fit(Manipulations::FIT_CONTAIN, 270, 350);
}
/**
* Products
*/
public function products(): MorphToMany
public function products(): BelongsToMany
{
return $this->morphToMany(Product::class, 'productable', 'product_has_relations');
return $this->belongsToMany(Product::class, 'collection_product');
}
/**

View File

@@ -2,9 +2,11 @@
namespace App\Models\Ecommerce\Product\Order;
use App\Models\Concerns\HasSchemalessAttributes;
use App\Models\Ecommerce\Product\Order\Concerns\HasPayments;
use App\Models\Ecommerce\Product\Order\Concerns\HasShipping;
use App\Models\Ecommerce\Product\Order\Concerns\HasStatus;
use App\Models\Ecommerce\Product\Order\Status\OrderStatus;
use App\Models\System\Settings\Location\Province;
use App\Models\System\Settings\Payments\PaymentType;
use App\Models\User;
@@ -18,6 +20,7 @@ class Order extends Model
{
use HasFactory;
use HasPayments;
use HasSchemalessAttributes;
use HasShipping;
use HasStatus;
use SoftDeletes;
@@ -89,4 +92,14 @@ class Order extends Model
{
return $this->belongsTo(PaymentType::class, 'payment_type_id');
}
/**
* Booted
*/
protected static function booted(): void
{
static::creating(function (Order $order) {
$order->status = $order->status ?? OrderStatus::default();
});
}
}

View File

@@ -43,6 +43,7 @@ class OrderStatus
public static function values(): array
{
return [
'' => '-',
self::PENDING => __('Pending'),
self::REGISTER => __('Registered'),
self::PAID => __('Paid'),
@@ -65,6 +66,7 @@ class OrderStatus
public static function classes(): array
{
return [
'' => 'warning',
self::PENDING => 'warning',
self::REGISTER => 'info',
self::PAID => 'primary',
@@ -79,6 +81,7 @@ class OrderStatus
public static function colors(): array
{
return [
'' => '#F5573B',
self::PENDING => '#F5573B',
self::REGISTER => '#F2CB22',
self::PAID => '#098F56',

View File

@@ -23,7 +23,7 @@ trait HasPropertiesJson
foreach ($this->properties as $property) {
$attributeSlug = $property->attribute->slug;
if (! isset($propertiesJson[$attributeSlug])) {
$propertiesJson[$attributeSlug] = [];
}
@@ -34,12 +34,12 @@ trait HasPropertiesJson
if ($value->value) {
$propertiesJson[$attributeSlug][] = $value->value->key;
}
if ($value->product_custom_value) {
$propertiesJson[$attributeSlug][] = $value->product_custom_value;
}
}
// Unique values just in case
$propertiesJson[$attributeSlug] = array_values(array_unique($propertiesJson[$attributeSlug]));
}

View File

@@ -21,32 +21,20 @@ trait ProductMedia
*/
public function registerMediaConversions(?Media $media = null): void
{
$this->addMediaConversion('thumb200x200')
->fit(Manipulations::FIT_CONTAIN, 200, 200);
$this->addMediaConversion('thumb400x400')
->fit(Manipulations::FIT_CONTAIN, 400, 400);
$this->addMediaConversion('thumb720x720')
->fit(Manipulations::FIT_CONTAIN, 720, 720);
$this->addMediaConversion('thumb800x800')
->fit(Manipulations::FIT_CONTAIN, 800, 800);
$this->addMediaConversion('thumb1200x1200')
->fit(Manipulations::FIT_CONTAIN, 1200, 1200);
$this->addMediaConversion('thumb288x431')
->fit(Manipulations::FIT_CONTAIN, 288, 431);
$this->addMediaConversion('thumb270x350')
->fit(Manipulations::FIT_CONTAIN, 270, 350);
}
/**
* Thumbnail
*/
public function thumbnail(string $size = '200x200'): string
public function thumbnail(string $size = '400x400'): string
{
return $this->getFirstMediaUrl('uploads', 'thumb'.$size);
}
@@ -54,7 +42,7 @@ trait ProductMedia
/**
* Get image when hovered (returns second image)
*/
public function getHoverImage(string $size = '270x350'): string
public function getHoverImage(string $size = '400x400'): string
{
$media = $this->getMedia('uploads');
$image_count = $media->count();

View File

@@ -5,7 +5,7 @@ namespace App\Models\Ecommerce\Product\Product\Concerns;
use App\Models\Common\Comment;
use App\Models\Ecommerce\Channel\Channel;
use App\Models\Ecommerce\Product\Brand\Brand;
use App\Models\Ecommerce\Product\Cart\Cart;
use App\Models\Ecommerce\Product\Cart\CartItem;
use App\Models\Ecommerce\Product\Category\Category;
use App\Models\Ecommerce\Product\Collection\Collection;
use App\Models\Ecommerce\Product\Inventory\Inventory;
@@ -15,7 +15,6 @@ use App\Models\Ecommerce\Product\Review\Review;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
trait ProductRelationships
{
@@ -28,8 +27,8 @@ trait ProductRelationships
}
/**
+ * Parent
+ */
* Parent
*/
public function parent(): BelongsTo
{
return $this->belongsTo(Product::class, 'parent_id');
@@ -38,9 +37,9 @@ trait ProductRelationships
/**
* Related Channels
*/
public function channels(): MorphToMany
public function channels(): BelongsToMany
{
return $this->morphedByMany(Channel::class, 'productable', 'product_has_relations');
return $this->belongsToMany(Channel::class, 'channel_product');
}
/**
@@ -56,25 +55,25 @@ trait ProductRelationships
/**
* Related products (similar)
*/
public function relatedProducts(): MorphToMany
public function relatedProducts(): BelongsToMany
{
return $this->morphedByMany(Product::class, 'productable', 'product_has_relations');
return $this->belongsToMany(Product::class, 'product_related', 'product_id', 'related_product_id');
}
/**
* Related categories
*/
public function categories(): MorphToMany
public function categories(): BelongsToMany
{
return $this->morphedByMany(Category::class, 'productable', 'product_has_relations');
return $this->belongsToMany(Category::class, 'category_product');
}
/**
* Related Collections
*/
public function collections(): MorphToMany
public function collections(): BelongsToMany
{
return $this->morphedByMany(Collection::class, 'productable', 'product_has_relations');
return $this->belongsToMany(Collection::class, 'collection_product');
}
/**
@@ -109,7 +108,7 @@ trait ProductRelationships
*/
public function carts(): BelongsTo
{
return $this->belongsTo(Cart::class);
return $this->belongsTo(CartItem::class);
}
/**

View File

@@ -27,16 +27,16 @@ class Product extends Model implements HasMedia, Viewable
*/
use HasFactory;
/**
* Has Schemaless Attributes (spatie/laravel-schemaless-attributes)
*/
use HasSchemalessAttributes;
/**
* Has Properties Json
*/
use HasPropertiesJson;
/**
* Has Schemaless Attributes (spatie/laravel-schemaless-attributes)
*/
use HasSchemalessAttributes;
/**
* Has Slug (spatie/laravel-sluggable)
*/

View File

@@ -0,0 +1,46 @@
<?php
namespace App\Models\Ecommerce\Product\ProductView;
use App\Models\Ecommerce\Product\Product\Product;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class ProductView extends Model
{
use HasFactory;
/**
* The table associated with the model.
*/
protected $table = 'product_views';
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'user_id',
'product_id',
'updated_at',
];
/**
* Product
*/
public function product(): BelongsTo
{
return $this->belongsTo(Product::class);
}
/**
* User
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}

View File

@@ -9,7 +9,7 @@ use Illuminate\Database\Eloquent\Model;
* @property int $id
* @property string $version
* @property string $os
* @property bool $important
* @property bool $important
* @property string $notes
* @property \Carbon\Carbon|null $created_at
* @property \Carbon\Carbon|null $updated_at

View File

@@ -9,6 +9,7 @@ use App\Models\Concerns\InteractsWithRoles;
use App\Models\Ecommerce\Product\Cart\CartItem;
use App\Models\Ecommerce\Product\Favorite\Favorite;
use App\Models\Ecommerce\Product\Order\Order;
use App\Models\Ecommerce\Product\ProductView\ProductView;
use App\Models\Ecommerce\Product\Review\Review;
use App\Models\Post\User\UserDoc;
use App\Models\System\Settings\Location\UserAddress;
@@ -128,6 +129,14 @@ class User extends Authenticatable
return $this->hasMany(Favorite::class);
}
/**
* User's viewed products
*/
public function productViews(): HasMany
{
return $this->hasMany(ProductView::class);
}
/**
* User's favorite products
*/

View File

@@ -62,7 +62,7 @@ class MostSoldProducts extends Lens
{
return [
ID::make(__('ID'), 'id')->sortable(),
Images::make(__('Image'), 'uploads')->conversionOnIndexView('thumb200x200'),
Images::make(__('Image'), 'uploads')->conversionOnIndexView('thumb400x400'),
Text::make(__('Name'), 'name')->sortable(),
Number::make(__('Price'), 'price_amount')->sortable(),

View File

@@ -81,7 +81,7 @@ class Banner extends Resource
ID::make()->sortable(),
Images::make(__('Image'), 'main')
->conversionOnIndexView('thumb200x200')
->conversionOnIndexView('thumb400x400')
->rules('required')
->required(),

View File

@@ -90,7 +90,7 @@ class Channel extends Resource
ID::make()->sortable(),
Images::make(__('Image'), 'uploads')
->conversionOnIndexView('thumb200x200')
->conversionOnIndexView('thumb400x400')
->rules('required')
->required(),

View File

@@ -18,7 +18,7 @@ class ChannelFieldsForIndex
ID::make()->hidden(),
Images::make(__('Image'), 'uploads')
->conversionOnIndexView('thumb200x200'),
->conversionOnIndexView('thumb400x400'),
Text::make(__('Name'), 'name')
->sortable(),

View File

@@ -96,7 +96,7 @@ class Brand extends Resource
ID::make()->sortable(),
Images::make(__('Image'), 'uploads')
->conversionOnIndexView('thumb200x200')
->conversionOnIndexView('thumb400x400')
->rules('required')
->required(),

View File

@@ -83,7 +83,7 @@ class Category extends Resource
ID::make()->sortable(),
Images::make(__('Image'), 'uploads')
->conversionOnIndexView('thumb200x200')
->conversionOnIndexView('thumb400x400')
->rules('required')
->required(),

View File

@@ -0,0 +1,120 @@
<?php
namespace App\Nova\Resources\Ecommerce\Product\Category;
use App\Models\Ecommerce\Product\Category\SelectedCategory as SelectedCategoryModel;
use App\Nova\Resource;
use Laravel\Nova\Fields\BelongsToMany;
use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Fields\Textarea;
use Laravel\Nova\Http\Requests\NovaRequest;
use Trin4ik\NovaSwitcher\NovaSwitcher;
class SelectedCategory extends Resource
{
/**
* The model the resource corresponds to.
*
* @var class-string<SelectedCategoryModel>
*/
public static $model = SelectedCategoryModel::class;
/**
* The single value that should be used to represent the resource when being displayed.
*
* @var string
*/
public static $title = 'name';
/**
* The columns that should be searched.
*
* @var array
*/
public static $search = [
'id', 'name',
];
/**
* Get the displayable label of the resource.
*/
public static function label(): string
{
return __('Sections');
}
/**
* Get the displayable singular label of the resource.
*/
public static function singularLabel(): string
{
return __('Section');
}
/**
* Get the fields displayed by the resource.
*
* @return array
*/
public function fields(NovaRequest $request)
{
return [
ID::make()->sortable(),
Text::make(__('Name'), 'name')
->sortable()
->translatable()
->rules('required'),
Textarea::make(__('Description'), 'description')
->translatable()
->nullable(),
NovaSwitcher::make(__('Is Visible'), 'is_visible')
->default(true),
BelongsToMany::make(__('Categories'), 'categories', Category::class),
];
}
/**
* Get the cards available for the request.
*
* @return array
*/
public function cards(NovaRequest $request)
{
return [];
}
/**
* Get the filters available for the resource.
*
* @return array
*/
public function filters(NovaRequest $request)
{
return [];
}
/**
* Get the lenses available for the resource.
*
* @return array
*/
public function lenses(NovaRequest $request)
{
return [];
}
/**
* Get the actions available for the resource.
*
* @return array
*/
public function actions(NovaRequest $request)
{
return [];
}
}

View File

@@ -76,7 +76,7 @@ class Collection extends Resource
ID::make()->sortable(),
Images::make(__('Image'), 'uploads')
->conversionOnIndexView('thumb200x200')
->conversionOnIndexView('thumb400x400')
->rules('required')
->required(),

View File

@@ -81,7 +81,7 @@ class ProductResource extends Resource
{
return [
ID::make()->sortable(),
Images::make(__('Image'), 'uploads')->conversionOnIndexView('thumb200x200'),
Images::make(__('Image'), 'uploads')->conversionOnIndexView('thumb400x400'),
Text::make(__('Name'), fn () => $this->novaDetailPage())
->displayUsing(FieldHelpers::asLink(
link: $this->novaDetailPage(),

View File

@@ -27,7 +27,7 @@ class OrderFieldsForCreate
return [
Hidden::make('number')->default(Str::random(30)),
Hidden::make('user_id')->default($request->user()->id),
Hidden::make('source_app')->default(OS::ADMIN),
Hidden::make('source')->default(OS::ADMIN),
ID::make(),

View File

@@ -67,7 +67,7 @@ class OrderFieldsForDetail
)
->asHtml(),
Select::make(__('App'), 'source_app')
Select::make(__('App'), 'source')
->displayUsingLabels()
->options(OS::apps())
->sortable(),

View File

@@ -55,7 +55,7 @@ class OrderFieldsForIndex
->default(OrderShipping::default())
->sortable(),
Select::make(__('Source'), 'source_app')
Select::make(__('Source'), 'source')
->displayUsingLabels()
->options(OS::apps())
->sortable(),

View File

@@ -93,7 +93,7 @@ class ProductFieldsForCreate
->rules('nullable', 'string'),
Images::make(__('Image'), 'uploads')
->conversionOnIndexView('thumb200x200')
->conversionOnIndexView('thumb400x400')
->rules('required')
->setFileName(NovaForm::fillMediaFileName())
->required(),

View File

@@ -53,7 +53,7 @@ class ProductFieldsForDetail
Text::make(__('Name'), 'name'),
Images::make(__('Image'), 'uploads')
->conversionOnIndexView('thumb200x200'),
->conversionOnIndexView('thumb400x400'),
Trix::make(__('Description'), 'description')->withFiles('public')->alwaysShow(),
Text::make(__('Price'), 'cost_amount'),
@@ -134,8 +134,8 @@ class ProductFieldsForDetail
'name' => $property->attribute->slug,
'type' => $property->attribute->type,
'default' => $property->attribute->type === 'select'
? $property->values->first()->value?->id
: $property->values->first()->product_custom_value,
? $property->values->first()->value?->id ?? '-'
: $property->values->first()->product_custom_value ?? '-',
'options' => $property->attribute->values->map(fn ($value) => [
'label' => $value->value,
'value' => $value->id,

View File

@@ -26,7 +26,7 @@ class ProductFieldsForIndex
return [
ID::make()->sortable(),
Images::make(__('Image'), 'uploads')->conversionOnIndexView('thumb200x200'),
Images::make(__('Image'), 'uploads')->conversionOnIndexView('thumb400x400'),
Text::make(__('Name'), 'name')->sortable(),
BelongsTo::make(__('Brand'), 'brand', Brand::class)

View File

@@ -32,7 +32,7 @@ class VariantFieldsForDetail
BelongsTo::make(__('Parent'), 'parent', Product::class),
Images::make(__('Image'), 'uploads')
->conversionOnIndexView('thumb200x200'),
->conversionOnIndexView('thumb400x400'),
Text::make(__('Price'), 'cost_amount')
->rules('required', 'numeric'),

View File

@@ -20,7 +20,7 @@ class VariantFieldsForIndex
ID::make()->sortable(),
Images::make(__('Image'), 'uploads')
->conversionOnIndexView('thumb200x200'),
->conversionOnIndexView('thumb400x400'),
Text::make(__('Price'), 'cost_amount')
->rules('required', 'numeric'),

View File

@@ -33,9 +33,8 @@ class ProductEntrepreneurFilter extends Filter
*/
public function apply(NovaRequest $request, $query, $value)
{
$vendorProducts = DB::table('product_has_relations')
->where('productable_type', 'channel')
->where('productable_id', $value)
$vendorProducts = DB::table('channel_product')
->where('channel_id', $value)
->pluck('product_id');
$query->whereIntegerInRaw('id', $vendorProducts);

View File

@@ -123,9 +123,8 @@ class Product extends Resource
$user = $request->user();
if ($user->hasRole('vendor')) {
$vendorProducts = DB::table('product_has_relations')
->where('productable_type', 'channel')
->where('productable_id', $user->channel()->id)
$vendorProducts = DB::table('channel_product')
->where('channel_id', $user->channel()->id)
->pluck('product_id');
$query->whereIntegerInRaw('id', $vendorProducts);

View File

@@ -38,7 +38,6 @@ class Warning extends Resource
/**
* Get the fields displayed by the resource.
*
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
* @return array
*/
public function fields(NovaRequest $request)
@@ -68,7 +67,6 @@ class Warning extends Resource
/**
* Get the cards available for the request.
*
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
* @return array
*/
public function cards(NovaRequest $request)
@@ -79,7 +77,6 @@ class Warning extends Resource
/**
* Get the filters available for the resource.
*
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
* @return array
*/
public function filters(NovaRequest $request)
@@ -90,7 +87,6 @@ class Warning extends Resource
/**
* Get the lenses available for the resource.
*
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
* @return array
*/
public function lenses(NovaRequest $request)
@@ -101,7 +97,6 @@ class Warning extends Resource
/**
* Get the actions available for the resource.
*
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
* @return array
*/
public function actions(NovaRequest $request)

View File

@@ -64,8 +64,8 @@ class ChannelPolicy
*/
public function update(User $user, Channel $channel): Response
{
if ($user->hasRole(['admin'])) {
return $this->allow();
if (tmpostChannel()->slug === $channel->slug) {
return $this->deny();
}
return $this->deny();

View File

@@ -139,7 +139,7 @@ class AuthServiceProvider extends ServiceProvider
Gate::define('isVendor', fn ($user) => $user->hasRole('vendor'));
Gate::define('viewApiDocs', function (User $user) {
return in_array($user->email, ['nurmuhammet@mail.com']);
return in_array($user->email, ['nurmuhammet@mail.com', 'admin@shop.post.tm']);
});
}
}

View File

@@ -2,11 +2,11 @@
namespace App\Providers;
use Dedoc\Scramble\Support\Generator\SecurityScheme;
use Illuminate\Support\ServiceProvider;
use Dedoc\Scramble\Scramble;
use Dedoc\Scramble\Support\Generator\OpenApi;
use Dedoc\Scramble\Support\Generator\SecurityRequirement;
use Dedoc\Scramble\Support\Generator\SecurityScheme;
use Illuminate\Support\ServiceProvider;
class DocumentationServiceProvider extends ServiceProvider
{
@@ -24,14 +24,14 @@ class DocumentationServiceProvider extends ServiceProvider
public function boot(): void
{
Scramble::configure()
->withDocumentTransformers(function (OpenApi $openApi) {
$openApi->components->securitySchemes['api-token'] = SecurityScheme::apiKey('header', 'Api-token');
$openApi->components->securitySchemes['bearer'] = SecurityScheme::http('bearer');
->withDocumentTransformers(function (OpenApi $openApi) {
$openApi->components->securitySchemes['api-token'] = SecurityScheme::apiKey('header', 'Api-token');
$openApi->components->securitySchemes['bearer'] = SecurityScheme::http('bearer');
$openApi->security[] = new SecurityRequirement([
'api-token' => [],
'bearer' => [],
]);
});
$openApi->security[] = new SecurityRequirement([
'api-token' => [],
'bearer' => [],
]);
});
}
}

View File

@@ -15,6 +15,7 @@ use App\Nova\Resources\Ecommerce\Payout\PayoutResource;
use App\Nova\Resources\Ecommerce\Product\Attribute\Attribute;
use App\Nova\Resources\Ecommerce\Product\Brand\Brand;
use App\Nova\Resources\Ecommerce\Product\Category\Category;
use App\Nova\Resources\Ecommerce\Product\Category\SelectedCategory;
use App\Nova\Resources\Ecommerce\Product\Collection\Collection;
use App\Nova\Resources\Ecommerce\Product\Coupon\Coupon;
use App\Nova\Resources\Ecommerce\Product\Inventory\Inventory;
@@ -158,6 +159,7 @@ class NovaServiceProvider extends NovaApplicationServiceProvider
MenuItem::resource(Category::class),
MenuItem::resource(Brand::class),
MenuItem::resource(Attribute::class),
MenuItem::resource(SelectedCategory::class),
])->icon('color-swatch'),
])->icon('shopping-bag')->collapsedByDefault(),

View File

@@ -1,58 +1,17 @@
<?php
declare(strict_types=1);
namespace App\Repositories\Ecommerce\Order;
use App\Events\Ecommerce\Product\Order\OrderCreated;
use App\Models\Ecommerce\Product\Order\Order;
use App\Models\Ecommerce\Product\Order\Shipping\OrderShipping;
use Illuminate\Support\Facades\DB;
class OrderRepository
{
/**
* Order repo
*/
public function __construct(
protected array $data = [],
) {}
/**
* Create new order
*/
public function create()
{
$order = Order::create($this->data);
auth()->user()->carts()->with(['product' => [
'media',
'channels',
]])->get()->each(function ($cart) use ($order) {
DB::table('order_items')->insert([
'product_name' => $cart->product->name,
'product_id' => $cart->product_id,
'order_id' => $order->id,
'channel_id' => $cart->product->channels->first()?->id ?? tmpostChannel()->id,
'quantity' => $cart->product_quantity,
'unit_price_amount' => $cart->product->price_amount,
'unit_cost_amount' => $cart->product->cost_amount,
'created_at' => now(),
'updated_at' => now(),
]);
$cart->product->update([
'stock' => $cart->product->stock - $cart->product_quantity,
]);
});
auth()->user()->carts()->delete();
OrderCreated::dispatch($order);
return $order;
}
/**
* Available times
*
* @return array<string, mixed>
*/
public static function availableTimes(): array
{

View File

@@ -3,7 +3,6 @@
namespace App\Repositories\Ecommerce\Product\Category;
use App\Models\Ecommerce\Product\Category\Category;
use App\Repositories\System\Cache\CacheRepository;
use Illuminate\Http\Request;
class CategoryRepository
@@ -124,16 +123,13 @@ class CategoryRepository
/**
* Names with taxes (usefull for nova)
*/
public static function namesWithTaxes(): array
public static function namesWithTaxes(): mixed
{
return CacheRepository::make(
name: 'cs-nova-models-categories',
value: fn () => static::maskParentName(
Category::tree()
->where('is_visible', true)
->get(['id', 'slug', 'name', 'tax_percentage', 'parent_id', 'is_visible'])
->toTree()
)
return static::maskParentName(
Category::tree()
->where('is_visible', true)
->get(['id', 'slug', 'name', 'tax_percentage', 'parent_id', 'is_visible'])
->toTree()
);
}
@@ -181,9 +177,8 @@ class CategoryRepository
])) {
$products = $resource->products()->distinct('products.id')->pluck('products.id');
return $this->queryBuilder->join('product_has_relations', 'categories.id', '=', 'product_has_relations.productable_id')
->where('product_has_relations.productable_type', '=', 'category')
->whereIntegerInRaw('product_has_relations.product_id', $products)
return $this->queryBuilder->join('category_product', 'categories.id', '=', 'category_product.category_id')
->whereIntegerInRaw('category_product.product_id', $products)
->distinct('categories.id')
->get(['id', 'slug', 'name']);
}

View File

@@ -1,11 +1,15 @@
<?php
declare(strict_types=1);
namespace App\Repositories\Ecommerce\Product;
use App\Helpers\Ecommerce\Product\Filter\ProductFilterer;
use App\Helpers\Ecommerce\Product\Sort\ProductSorter;
use App\Models\Ecommerce\Product\Product\Product;
use Illuminate\Contracts\Pagination\Paginator;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -21,7 +25,7 @@ class ProductRepository
*
* @var \Illuminate\Database\Eloquent\Builder
*/
protected mixed $queryBuilder;
protected $queryBuilder;
/**
* Application request
@@ -31,7 +35,7 @@ class ProductRepository
/**
* Relationships to eager load
*
* @var array<int, string>
* @var array<int, string|array>
*/
protected array $with = [];
@@ -54,6 +58,8 @@ class ProductRepository
/**
* Update query builder with resource relationship
*
* @param mixed $resource
*/
public function queryAsFromResource($resource): self
{
@@ -119,7 +125,7 @@ class ProductRepository
public function applySearchQueries(): self
{
if (request()->filled('q')) {
$searcQuery = str_replace([
$searchQuery = str_replace([
'\\',
'(',
')',
@@ -128,7 +134,7 @@ class ProductRepository
], '', request('q'));
// Search by name
$this->queryBuilder->where('products.name', '~*', $searcQuery);
$this->queryBuilder->where('products.name', '~*', $searchQuery);
}
return $this;
@@ -145,7 +151,21 @@ class ProductRepository
}
/**
* "Where IN" clouse
* Filter by viewed by user
*/
public function applyViewedBy($user): self
{
$this->queryBuilder
->join('product_views', 'products.id', '=', 'product_views.product_id')
->where('product_views.user_id', $user->id)
->orderBy('product_views.updated_at', 'desc')
->select('products.*');
return $this;
}
/**
* "Where IN" clause
*/
public function whereIn(string $attribute, array $value): self
{
@@ -155,7 +175,7 @@ class ProductRepository
}
/**
* "where integer in raw" clouse
* "where integer in raw" clause
*/
public function whereIntegerInRaw(string $attribute, array $value): self
{
@@ -180,7 +200,7 @@ class ProductRepository
/**
* Get the results
*/
public function get()
public function get(): Collection
{
$this->eagerLoadRelationships();
@@ -257,6 +277,8 @@ class ProductRepository
/**
* Ajax paginate
*
* @param mixed $products
*/
public static function ajaxPaginate($products): JsonResponse
{

View File

@@ -0,0 +1,72 @@
<?php
declare(strict_types=1);
namespace App\Services\Order;
use App\Events\Ecommerce\Product\Order\OrderCreated;
use App\Models\Ecommerce\Product\Order\Order;
use App\Models\User;
use Illuminate\Support\Facades\DB;
class CreateOrderService
{
/**
* Create a new order for the user
*/
public function execute(User $user, array $data): Order
{
return DB::transaction(function () use ($user, $data) {
// 1. Create the order
$order = Order::create($data);
// 2. Process Cart Items
$user->carts()
->with(['product' => function ($query) {
$query->with(['media', 'channels']);
}])
->get()
->each(function ($cart) use ($order) {
// Create Order Item
DB::table('order_items')->insert([
'product_name' => $cart->product->name,
'product_id' => $cart->product_id,
'order_id' => $order->id,
'channel_id' => $cart->product->channels->first()?->id ?? tmpostChannel()->id,
'quantity' => $cart->product_quantity,
'unit_price_amount' => $cart->product->price_amount,
'unit_cost_amount' => $cart->product->cost_amount,
'created_at' => now(),
'updated_at' => now(),
]);
// Update Stock directly in products table, also relationship
$stock = $cart->product->stock - $cart->product_quantity;
$cart->product->update([
'stock' => $stock,
]);
$data = DB::table('inventory_product')->where('product_id', $cart->product_id)->first();
if ($data) {
DB::table('inventory_product')->where('id', $data->id)->update([
'stock' => $stock,
]);
} else {
warn('Product has no inventory record', json_encode([
'product_id' => $cart->product_id,
'order_id' => $order->id,
]));
}
});
// 3. Clear User Cart
$user->carts()->delete();
// 4. Dispatch Event
OrderCreated::dispatch($order);
return $order;
});
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace App\Support;
use Illuminate\Support\Str;
use Spatie\MediaLibrary\Conversions\Conversion;
use Spatie\MediaLibrary\Support\FileNamer\FileNamer;
class ShortFileNamer extends FileNamer
{
/**
* Generate a short random name for the original file.
*/
public function originalFileName(string $fileName): string
{
return Str::random(10);
}
public function conversionFileName(string $fileName, Conversion $conversion): string
{
return $conversion->getName();
}
public function responsiveFileName(string $fileName): string
{
return 'res';
}
}

View File

@@ -58,7 +58,7 @@ return [
/*
* This is the class that is responsible for naming generated files.
*/
'file_namer' => Spatie\MediaLibrary\Support\FileNamer\DefaultFileNamer::class,
'file_namer' => App\Support\ShortFileNamer::class,
/*
* The class that contains the strategy for determining a media file's path.

3
database/data/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
*
!provinces.json
!.gitignore

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

View File

@@ -1,30 +0,0 @@
[
{
"id": 4,
"created_at": "2022-06-16 15:21:07",
"updated_at": "2023-11-22 16:59:16",
"name": "{\"tk\":\"Renk\",\"ru\":\"\\u0426\\u0432\\u0435\\u0442\",\"en\":\"Colour\"}",
"slug": "colour",
"description": "{\"en\":null}",
"type": "select",
"is_enabled": true,
"is_searchable": true,
"is_filterable": true,
"category_id": null,
"is_required": false
},
{
"id": 5,
"created_at": "2022-06-16 15:57:21",
"updated_at": "2023-06-06 16:12:51",
"name": "{\"tk\":\"\\u00d6l\\u00e7eg\",\"ru\":\"\\u0420\\u0430\\u0437\\u043c\\u0435\\u0440\",\"en\":\"Size\"}",
"slug": "size",
"description": "{\"en\":null}",
"type": "text",
"is_enabled": true,
"is_searchable": true,
"is_filterable": true,
"category_id": null,
"is_required": false
}
]

View File

@@ -1,72 +0,0 @@
[
{
"id": 2,
"position": null,
"extra_attributes": null,
"link": null,
"is_visible": true,
"description": "{\"tk\":null}",
"created_at": "2022-10-15 10:10:04",
"updated_at": "2023-05-25 17:58:31",
"banner_type": "category",
"banner_resource": "5",
"place": "first",
"sort_order": 2
},
{
"id": 3,
"position": null,
"extra_attributes": null,
"link": null,
"is_visible": true,
"description": "{\"tk\":null}",
"created_at": "2023-05-02 14:55:43",
"updated_at": "2023-05-25 17:58:31",
"banner_type": "category",
"banner_resource": "20",
"place": "first",
"sort_order": 1
},
{
"id": 4,
"position": null,
"extra_attributes": null,
"link": null,
"is_visible": true,
"description": "{\"tk\":null}",
"created_at": "2023-06-20 22:51:53",
"updated_at": "2023-07-12 20:27:50",
"banner_type": "brands",
"banner_resource": "14",
"place": "market",
"sort_order": null
},
{
"id": 5,
"position": null,
"extra_attributes": null,
"link": null,
"is_visible": true,
"description": "{\"tk\":null}",
"created_at": "2023-06-20 22:58:52",
"updated_at": "2023-09-12 16:02:09",
"banner_type": "brands",
"banner_resource": "306",
"place": "store",
"sort_order": null
},
{
"id": 9,
"position": null,
"extra_attributes": null,
"link": null,
"is_visible": false,
"description": "{\"tk\":null}",
"created_at": "2023-10-30 14:48:23",
"updated_at": "2023-11-16 15:54:40",
"banner_type": "brands",
"banner_resource": "14",
"place": "short_ad",
"sort_order": null
}
]

File diff suppressed because it is too large Load Diff

View File

@@ -1,226 +0,0 @@
[
{
"id": 14,
"position": null,
"extra_attributes": null,
"link": null,
"is_visible": true,
"description": "{\"tk\":null}",
"created_at": "2022-06-23 23:56:38",
"updated_at": "2023-09-14 09:57:56",
"banner_type": "category",
"banner_resource": "82",
"place": "first",
"sort_order": 3
},
{
"id": 22,
"position": null,
"extra_attributes": null,
"link": null,
"is_visible": true,
"description": "{\"tk\":null}",
"created_at": "2022-09-02 19:08:44",
"updated_at": "2023-09-14 09:57:56",
"banner_type": "brands",
"banner_resource": "14",
"place": "first",
"sort_order": 4
},
{
"id": 26,
"position": null,
"extra_attributes": null,
"link": null,
"is_visible": true,
"description": "{\"tk\":null}",
"created_at": "2022-12-07 10:12:38",
"updated_at": "2023-09-14 09:57:56",
"banner_type": "category",
"banner_resource": "309",
"place": "first",
"sort_order": 3
},
{
"id": 33,
"position": null,
"extra_attributes": null,
"link": null,
"is_visible": true,
"description": "{\"tk\":null}",
"created_at": "2023-03-09 09:15:06",
"updated_at": "2023-09-14 09:57:56",
"banner_type": "category",
"banner_resource": "234",
"place": "first",
"sort_order": 2
},
{
"id": 35,
"position": null,
"extra_attributes": null,
"link": null,
"is_visible": true,
"description": "{\"tk\":null}",
"created_at": "2023-04-24 13:05:45",
"updated_at": "2023-09-14 09:57:56",
"banner_type": "category",
"banner_resource": "1",
"place": "first",
"sort_order": 4
},
{
"id": 37,
"position": null,
"extra_attributes": null,
"link": null,
"is_visible": true,
"description": "{\"tk\":null}",
"created_at": "2023-05-03 12:00:36",
"updated_at": "2023-09-14 09:57:56",
"banner_type": "category",
"banner_resource": "446",
"place": "first",
"sort_order": 1
},
{
"id": 39,
"position": null,
"extra_attributes": null,
"link": null,
"is_visible": true,
"description": "{\"tk\":null}",
"created_at": "2023-05-19 16:35:25",
"updated_at": "2023-09-14 09:57:56",
"banner_type": "brands",
"banner_resource": "149",
"place": "first",
"sort_order": 3
},
{
"id": 41,
"position": null,
"extra_attributes": null,
"link": null,
"is_visible": true,
"description": "{\"tk\":null}",
"created_at": "2023-05-30 16:00:44",
"updated_at": "2023-09-14 09:57:56",
"banner_type": "category",
"banner_resource": "26",
"place": "first",
"sort_order": 5
},
{
"id": 42,
"position": null,
"extra_attributes": null,
"link": null,
"is_visible": true,
"description": "{\"tk\":null}",
"created_at": "2023-06-23 11:55:19",
"updated_at": "2023-09-14 09:57:56",
"banner_type": "category",
"banner_resource": "105",
"place": "first",
"sort_order": 6
},
{
"id": 43,
"position": null,
"extra_attributes": null,
"link": null,
"is_visible": true,
"description": "{\"tk\":null}",
"created_at": "2023-07-11 10:25:41",
"updated_at": "2023-09-14 09:57:56",
"banner_type": "category",
"banner_resource": "24",
"place": "first",
"sort_order": 8
},
{
"id": 44,
"position": null,
"extra_attributes": null,
"link": null,
"is_visible": true,
"description": "{\"tk\":null}",
"created_at": "2023-07-11 15:13:44",
"updated_at": "2023-09-14 09:57:56",
"banner_type": "category",
"banner_resource": "178",
"place": "first",
"sort_order": 7
},
{
"id": 45,
"position": null,
"extra_attributes": null,
"link": null,
"is_visible": true,
"description": "{\"tk\":null}",
"created_at": "2023-07-26 09:25:39",
"updated_at": "2023-09-14 09:57:56",
"banner_type": "category",
"banner_resource": "6",
"place": "first",
"sort_order": 9
},
{
"id": 46,
"position": null,
"extra_attributes": null,
"link": null,
"is_visible": true,
"description": "{\"tk\":null}",
"created_at": "2023-08-03 17:56:23",
"updated_at": "2023-09-14 09:57:56",
"banner_type": "category",
"banner_resource": "6",
"place": "first",
"sort_order": 10
},
{
"id": 47,
"position": null,
"extra_attributes": null,
"link": null,
"is_visible": true,
"description": "{\"tk\":null}",
"created_at": "2023-08-10 17:32:36",
"updated_at": "2023-09-14 09:57:56",
"banner_type": "category",
"banner_resource": "324",
"place": "first",
"sort_order": 2
},
{
"id": 48,
"position": null,
"extra_attributes": null,
"link": null,
"is_visible": true,
"description": "{\"tk\":null}",
"created_at": "2023-08-16 17:28:47",
"updated_at": "2023-09-14 09:57:56",
"banner_type": "brands",
"banner_resource": "303",
"place": "first",
"sort_order": null
},
{
"id": 49,
"position": null,
"extra_attributes": null,
"link": null,
"is_visible": false,
"description": "{\"tk\":null}",
"created_at": "2023-09-03 17:01:08",
"updated_at": "2023-09-20 12:05:13",
"banner_type": "brands",
"banner_resource": "306",
"place": "first",
"sort_order": null
}
]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,380 +0,0 @@
[
{
"id": 6,
"channel_id": 7,
"channelable_type": "App\\Models\\User",
"channelable_id": 11,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 27,
"channel_id": 28,
"channelable_type": "App\\Models\\User",
"channelable_id": 60,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 29,
"channel_id": 30,
"channelable_type": "App\\Models\\User",
"channelable_id": 103,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 31,
"channel_id": 32,
"channelable_type": "App\\Models\\User",
"channelable_id": 1,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 39,
"channel_id": 40,
"channelable_type": "App\\Models\\User",
"channelable_id": 340,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 63,
"channel_id": 64,
"channelable_type": "App\\Models\\User",
"channelable_id": 715,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 69,
"channel_id": 70,
"channelable_type": "App\\Models\\User",
"channelable_id": 836,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 70,
"channel_id": 71,
"channelable_type": "App\\Models\\User",
"channelable_id": 848,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 74,
"channel_id": 75,
"channelable_type": "App\\Models\\User",
"channelable_id": 1659,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 77,
"channel_id": 79,
"channelable_type": "App\\Models\\User",
"channelable_id": 1915,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 78,
"channel_id": 80,
"channelable_type": "App\\Models\\User",
"channelable_id": 1916,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 79,
"channel_id": 81,
"channelable_type": "App\\Models\\User",
"channelable_id": 1917,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 80,
"channel_id": 82,
"channelable_type": "App\\Models\\User",
"channelable_id": 1918,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 81,
"channel_id": 83,
"channelable_type": "App\\Models\\User",
"channelable_id": 1919,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 82,
"channel_id": 84,
"channelable_type": "App\\Models\\User",
"channelable_id": 1925,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 86,
"channel_id": 88,
"channelable_type": "App\\Models\\User",
"channelable_id": 2054,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 87,
"channel_id": 89,
"channelable_type": "App\\Models\\User",
"channelable_id": 2086,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 90,
"channel_id": 92,
"channelable_type": "App\\Models\\User",
"channelable_id": 2260,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 91,
"channel_id": 93,
"channelable_type": "App\\Models\\User",
"channelable_id": 2355,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 92,
"channel_id": 94,
"channelable_type": "App\\Models\\User",
"channelable_id": 2356,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 93,
"channel_id": 64,
"channelable_type": "App\\Models\\User",
"channelable_id": 1025,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 94,
"channel_id": 95,
"channelable_type": "App\\Models\\User",
"channelable_id": 2710,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 96,
"channel_id": 97,
"channelable_type": "App\\Models\\User",
"channelable_id": 2924,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 97,
"channel_id": 98,
"channelable_type": "App\\Models\\User",
"channelable_id": 2962,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 98,
"channel_id": 99,
"channelable_type": "App\\Models\\User",
"channelable_id": 3021,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 101,
"channel_id": 102,
"channelable_type": "App\\Models\\User",
"channelable_id": 3158,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 103,
"channel_id": 104,
"channelable_type": "App\\Models\\User",
"channelable_id": 3325,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 104,
"channel_id": 105,
"channelable_type": "App\\Models\\User",
"channelable_id": 3448,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 105,
"channel_id": 106,
"channelable_type": "App\\Models\\User",
"channelable_id": 3650,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 106,
"channel_id": 107,
"channelable_type": "App\\Models\\User",
"channelable_id": 3672,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 107,
"channel_id": 108,
"channelable_type": "App\\Models\\User",
"channelable_id": 3684,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 109,
"channel_id": 110,
"channelable_type": "App\\Models\\User",
"channelable_id": 4149,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 111,
"channel_id": 112,
"channelable_type": "App\\Models\\User",
"channelable_id": 4430,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 113,
"channel_id": 114,
"channelable_type": "App\\Models\\User",
"channelable_id": 4512,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 114,
"channel_id": 115,
"channelable_type": "App\\Models\\User",
"channelable_id": 4879,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 115,
"channel_id": 116,
"channelable_type": "App\\Models\\User",
"channelable_id": 5097,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 117,
"channel_id": 1,
"channelable_type": "App\\Models\\User",
"channelable_id": 16,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 118,
"channel_id": 118,
"channelable_type": "App\\Models\\User",
"channelable_id": 5777,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 122,
"channel_id": 122,
"channelable_type": "App\\Models\\User",
"channelable_id": 6633,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 123,
"channel_id": 123,
"channelable_type": "App\\Models\\User",
"channelable_id": 6717,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 124,
"channel_id": 124,
"channelable_type": "App\\Models\\User",
"channelable_id": 7002,
"default": false,
"created_at": null,
"updated_at": null
},
{
"id": 131,
"channel_id": 131,
"channelable_type": "App\\Models\\User",
"channelable_id": 7882,
"default": false,
"created_at": null,
"updated_at": null
}
]

View File

@@ -1,453 +0,0 @@
[
{
"id": 1,
"created_at": "2022-05-25 21:22:29",
"updated_at": "2023-07-14 10:00:33",
"name": "\"Türkmenpoçta\" PAK",
"slug": "tmpost",
"description": null,
"timezone": null,
"url": "https://shop.post.tm/",
"is_default": false
},
{
"id": 7,
"created_at": "2022-06-05 19:10:28",
"updated_at": "2022-06-05 19:10:28",
"name": "Muhammed Artykov shop",
"slug": "muhammed-artykov-shop",
"description": null,
"timezone": null,
"url": "https://shop.turkmenpost.gov.tm",
"is_default": false
},
{
"id": 28,
"created_at": "2022-07-23 13:21:05",
"updated_at": "2023-07-14 09:59:57",
"name": "Muratjan Juraýew",
"slug": "muratjan-jurayew",
"description": null,
"timezone": null,
"url": "https://shop.turkmenpost.gov.tm",
"is_default": false
},
{
"id": 30,
"created_at": "2022-07-27 16:54:15",
"updated_at": "2023-07-14 10:00:06",
"name": "Agajan Hekimow 1",
"slug": "sohrat",
"description": null,
"timezone": null,
"url": "https://shop.post.tm",
"is_default": false
},
{
"id": 32,
"created_at": "2022-08-18 23:57:41",
"updated_at": "2023-07-14 09:59:55",
"name": "Nurmuhammet Allanov",
"slug": "nurmuhammet-allanov",
"description": null,
"timezone": null,
"url": "https://shop.post.tm",
"is_default": false
},
{
"id": 40,
"created_at": "2022-08-31 11:06:29",
"updated_at": "2023-07-11 19:52:18",
"name": "AT Cybersport",
"slug": "at-cybersport",
"description": null,
"timezone": null,
"url": "https://shop.post.tm",
"is_default": true
},
{
"id": 64,
"created_at": "2022-10-07 11:06:54",
"updated_at": "2023-07-14 09:58:22",
"name": "Agajan Hekimow 8",
"slug": "juma",
"description": null,
"timezone": null,
"url": "https://shop.post.tm",
"is_default": false
},
{
"id": 70,
"created_at": "2022-10-25 16:23:50",
"updated_at": "2023-10-11 12:52:48",
"name": "Agajan Hekimow 2",
"slug": "market",
"description": null,
"timezone": null,
"url": "https://shop.post.tm",
"is_default": false
},
{
"id": 71,
"created_at": "2022-10-26 17:43:34",
"updated_at": "2023-08-02 13:04:19",
"name": "\"HEŞDEK\" ofis market",
"slug": "99365619032",
"description": null,
"timezone": null,
"url": "https://shop.post.tm",
"is_default": true
},
{
"id": 75,
"created_at": "2023-02-04 11:13:53",
"updated_at": "2023-07-14 09:58:25",
"name": "Agajan Hekimow 12",
"slug": "satlyk",
"description": null,
"timezone": null,
"url": "https://shop.post.tm",
"is_default": false
},
{
"id": 79,
"created_at": "2023-03-14 09:10:19",
"updated_at": "2023-07-14 09:58:27",
"name": "Agajan Hekimow 3",
"slug": "dowlet",
"description": null,
"timezone": null,
"url": "https://shop.post.tm",
"is_default": false
},
{
"id": 80,
"created_at": "2023-03-14 09:15:32",
"updated_at": "2023-07-21 10:23:34",
"name": "Amatly kosmetika",
"slug": "99361946997",
"description": null,
"timezone": null,
"url": "Agajan Hekimow 4",
"is_default": true
},
{
"id": 81,
"created_at": "2023-03-14 09:16:40",
"updated_at": "2023-07-14 09:58:29",
"name": "Agajan Hekimow 5",
"slug": "batyr99364707773",
"description": null,
"timezone": null,
"url": "https://shop.post.tm",
"is_default": false
},
{
"id": 82,
"created_at": "2023-03-14 09:17:24",
"updated_at": "2023-07-14 09:58:29",
"name": "Agajan Hekimow 6",
"slug": "pak",
"description": null,
"timezone": null,
"url": "https://shop.post.tm",
"is_default": false
},
{
"id": 83,
"created_at": "2023-03-14 09:17:59",
"updated_at": "2023-07-14 09:58:31",
"name": "Agajan Hekimow 7",
"slug": "muratjan",
"description": null,
"timezone": null,
"url": "https://shop.post.tm",
"is_default": false
},
{
"id": 84,
"created_at": "2023-03-15 09:49:14",
"updated_at": "2023-03-15 09:49:14",
"name": "Agajan Hekimow",
"slug": "agajan-hekimow",
"description": null,
"timezone": null,
"url": "https://shop.post.tm",
"is_default": true
},
{
"id": 88,
"created_at": "2023-04-04 16:54:41",
"updated_at": "2023-04-04 16:54:41",
"name": "Atajan Atajan",
"slug": "atajan-atajan",
"description": null,
"timezone": null,
"url": "https://shop.post.tm",
"is_default": true
},
{
"id": 89,
"created_at": "2023-04-08 09:14:30",
"updated_at": "2023-07-21 09:46:57",
"name": "Balyk tutmak we aw etmek",
"slug": "99365676855",
"description": null,
"timezone": null,
"url": "Agajan Hekimow 9",
"is_default": true
},
{
"id": 92,
"created_at": "2023-05-01 18:07:05",
"updated_at": "2023-07-21 09:43:32",
"name": "Mi",
"slug": "99365615764",
"description": null,
"timezone": null,
"url": "Agajan Hekimow 10",
"is_default": true
},
{
"id": 93,
"created_at": "2023-05-08 15:36:02",
"updated_at": "2023-07-21 10:07:24",
"name": "Akyayla",
"slug": "99365729774",
"description": null,
"timezone": null,
"url": "Agajan Hekimow 11",
"is_default": true
},
{
"id": 94,
"created_at": "2023-05-08 16:04:41",
"updated_at": "2023-07-14 09:58:11",
"name": "Ogulshat Berkeliyewa",
"slug": "ogulshat-berkeliyewa",
"description": null,
"timezone": null,
"url": null,
"is_default": false
},
{
"id": 95,
"created_at": "2023-05-23 14:16:00",
"updated_at": "2023-05-23 14:16:10",
"name": "Yakyndar",
"slug": "yakyndar",
"description": null,
"timezone": null,
"url": null,
"is_default": true
},
{
"id": 97,
"created_at": "2023-05-28 19:16:47",
"updated_at": "2023-07-14 09:58:49",
"name": "Gurdowa Gülşat",
"slug": "99363524158",
"description": null,
"timezone": null,
"url": null,
"is_default": false
},
{
"id": 98,
"created_at": "2023-05-30 10:05:29",
"updated_at": "2023-06-19 17:21:13",
"name": "Bezeg market",
"slug": "99362675545",
"description": null,
"timezone": null,
"url": null,
"is_default": true
},
{
"id": 99,
"created_at": "2023-06-02 14:36:02",
"updated_at": "2023-06-19 17:56:43",
"name": "Mannol-Turkmen",
"slug": "99365811591",
"description": null,
"timezone": null,
"url": null,
"is_default": true
},
{
"id": 102,
"created_at": "2023-06-08 17:17:58",
"updated_at": "2023-06-19 17:58:43",
"name": "Zyýada market",
"slug": "99363085015",
"description": null,
"timezone": null,
"url": null,
"is_default": true
},
{
"id": 104,
"created_at": "2023-06-14 14:21:24",
"updated_at": "2023-07-19 17:44:09",
"name": "Asia Tech",
"slug": "99362631593",
"description": null,
"timezone": null,
"url": null,
"is_default": true
},
{
"id": 105,
"created_at": "2023-06-19 14:15:36",
"updated_at": "2023-06-19 17:23:47",
"name": "Tehnopark",
"slug": "99365319225",
"description": null,
"timezone": null,
"url": null,
"is_default": true
},
{
"id": 106,
"created_at": "2023-07-01 20:10:15",
"updated_at": "2023-07-17 09:35:05",
"name": "Zeytun sport",
"slug": "zeytun-sport",
"description": null,
"timezone": null,
"url": "99362188328",
"is_default": false
},
{
"id": 107,
"created_at": "2023-07-04 15:12:41",
"updated_at": "2023-08-09 17:07:43",
"name": "Durmuş",
"slug": "durmus",
"description": null,
"timezone": null,
"url": "99363006990",
"is_default": false
},
{
"id": 108,
"created_at": "2023-07-05 14:59:29",
"updated_at": "2023-07-14 09:58:57",
"name": "Agajan Hekimow 14",
"slug": "suleyman",
"description": null,
"timezone": null,
"url": "99364564934",
"is_default": false
},
{
"id": 110,
"created_at": "2023-07-25 15:27:09",
"updated_at": "2023-08-05 17:56:31",
"name": "Hoşal",
"slug": "hosal",
"description": null,
"timezone": null,
"url": "+99361980857",
"is_default": false
},
{
"id": 112,
"created_at": "2023-08-01 09:05:01",
"updated_at": "2023-08-01 09:06:11",
"name": "Nusga haly",
"slug": "nusga-haly",
"description": null,
"timezone": null,
"url": "+99362695306",
"is_default": false
},
{
"id": 114,
"created_at": "2023-08-02 17:40:47",
"updated_at": "2023-08-02 17:42:46",
"name": "Elektronika.tm",
"slug": "elektronikatm",
"description": null,
"timezone": null,
"url": "+99363593666",
"is_default": false
},
{
"id": 115,
"created_at": "2023-08-08 10:54:39",
"updated_at": "2023-08-08 10:55:50",
"name": "Türkmenhaly",
"slug": "99364686669",
"description": null,
"timezone": null,
"url": null,
"is_default": false
},
{
"id": 116,
"created_at": "2023-08-14 10:35:47",
"updated_at": "2023-08-14 17:12:27",
"name": "Kaspian",
"slug": "kaspian",
"description": null,
"timezone": null,
"url": "+99365723298",
"is_default": true
},
{
"id": 118,
"created_at": "2023-09-02 13:24:58",
"updated_at": "2024-02-14 18:27:03",
"name": "Smart elektronika",
"slug": "smart-elektronika",
"description": null,
"timezone": null,
"url": null,
"is_default": true
},
{
"id": 122,
"created_at": "2023-10-02 18:21:20",
"updated_at": "2023-10-04 15:17:11",
"name": "Telekeçi 0050517",
"slug": "telekeci-0050517",
"description": null,
"timezone": null,
"url": "https://shop.post.tm",
"is_default": false
},
{
"id": 123,
"created_at": "2023-10-05 16:13:19",
"updated_at": "2023-11-12 12:54:44",
"name": "Opt.tm.",
"slug": "opt-tm",
"description": null,
"timezone": null,
"url": "+99361518808",
"is_default": true
},
{
"id": 124,
"created_at": "2023-10-17 22:04:23",
"updated_at": "2023-10-30 16:25:52",
"name": "Telekeçi 0043524",
"slug": "telekeci-0043524",
"description": null,
"timezone": null,
"url": "https://shop.post.tm",
"is_default": false
},
{
"id": 131,
"created_at": "2023-11-28 16:27:01",
"updated_at": "2024-02-06 16:08:41",
"name": "Gunar Kakajanowa",
"slug": "99365961072",
"description": null,
"timezone": null,
"url": "https://shop.post.tm",
"is_default": true
}
]

View File

@@ -1,770 +0,0 @@
[
{
"id": 1,
"created_at": "2022-06-08 18:16:01",
"updated_at": "2023-09-20 11:09:07",
"name": "{\"tk\":\"T\\u00e4ze harytlar\",\"ru\":\"\\u041d\\u043e\\u0432\\u044b\\u0435 \\u043f\\u0440\\u043e\\u0434\\u0443\\u043a\\u0442\\u044b\",\"en\":\"New products\"}",
"slug": "new-products",
"description": null,
"type": "manual",
"sort": null,
"match_conditions": "all",
"published_at": "2022-06-08 18:16:01+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 7
},
{
"id": 2,
"created_at": "2022-06-08 18:20:28",
"updated_at": "2024-02-21 16:12:24",
"name": "{\"tk\":\"Market\",\"ru\":\"\\u041c\\u0430\\u0440\\u043a\\u0435\\u0442\",\"en\":\"Market\"}",
"slug": "market",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": "all",
"published_at": "2022-06-08 18:20:28+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": false,
"sort_order": 43
},
{
"id": 3,
"created_at": "2022-09-19 14:28:45",
"updated_at": "2023-09-20 11:09:07",
"name": "{\"tk\":\"Arzanladylan harytlar\",\"ru\":\"\\u0422\\u043e\\u0432\\u0430\\u0440\\u044b \\u0441\\u043e \\u0441\\u043a\\u0438\\u0434\\u043a\\u043e\\u0439\",\"en\":\"Items on sale\"}",
"slug": "skidkaly-harytlar",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2022-09-19 09:24:22+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 3
},
{
"id": 5,
"created_at": "2022-10-14 15:46:47",
"updated_at": "2023-09-20 11:08:52",
"name": "{\"tk\":\"Ki\\u00e7i hojalyk tehnika\",\"ru\":\"\\u041c\\u0435\\u043b\\u043a\\u0430\\u044f \\u0431\\u044b\\u0442\\u043e\\u0432\\u0430\\u044f \\u0442\\u0435\\u0445\\u043d\\u0438\\u043a\\u0430\",\"en\":\"Small kitchen appliances\"}",
"slug": "kici-hojalyk-tehnika",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2022-10-14 10:39:35+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 20
},
{
"id": 6,
"created_at": "2022-10-27 09:48:48",
"updated_at": "2023-09-20 11:08:52",
"name": "{\"tk\":\"Balyk tutmak we aw etmek\",\"ru\":\"\\u0420\\u044b\\u0431\\u0430\\u043b\\u043a\\u0430 \\u0438 \\u043e\\u0445\\u043e\\u0442\\u0430\",\"en\":\"Fishing and hunting\"}",
"slug": "balyk-tutmak-we-aw-etmek",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2022-10-27 04:47:52+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 17
},
{
"id": 7,
"created_at": "2022-11-01 16:18:42",
"updated_at": "2023-09-20 11:08:52",
"name": "{\"tk\":\"Kansel\\u00fdar harytlary\",\"ru\":\"\\u041a\\u0430\\u043d\\u0446\\u0435\\u043b\\u044f\\u0440\\u0441\\u043a\\u0438\\u0435 \\u0442\\u043e\\u0432\\u0430\\u0440\\u044b\",\"en\":\"Stationery products\"}",
"slug": "kanselyariya-harytlary",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2022-11-01 11:17:24+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 21
},
{
"id": 10,
"created_at": "2022-11-17 09:14:10",
"updated_at": "2023-09-20 11:09:07",
"name": "{\"tk\":\"AT Cybersport\",\"ru\":\"AT Cybersport\",\"en\":\"AT Cybersport\"}",
"slug": "at-cybersport",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2022-11-17 04:13:16+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 4
},
{
"id": 13,
"created_at": "2023-02-10 10:44:04",
"updated_at": "2023-09-20 11:08:52",
"name": "{\"tk\":\"Brend sagatlar\",\"ru\":\"\\u0424\\u0438\\u0440\\u043c\\u0435\\u043d\\u043d\\u044b\\u0435 \\u0447\\u0430\\u0441\\u044b\",\"en\":\"Brand watches\"}",
"slug": "brend-sagatlar",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-02-10 05:43:02+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 22
},
{
"id": 14,
"created_at": "2023-02-14 09:23:37",
"updated_at": "2023-09-20 11:08:52",
"name": "{\"tk\":\"Blenderler\",\"ru\":\"\\u0411\\u043b\\u0435\\u043d\\u0434\\u0435\\u0440\\u044b\",\"en\":\"Blenders\"}",
"slug": "blendery",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-02-14 04:19:54+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 23
},
{
"id": 15,
"created_at": "2023-02-23 09:01:07",
"updated_at": "2023-09-20 11:08:52",
"name": "{\"tk\":\"\\u00dct\\u00fckler\",\"ru\":\"\\u0423\\u0442\\u044e\\u0433\\u0438\",\"en\":\"Irons\"}",
"slug": "utukler",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-02-23 03:58:07+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 24
},
{
"id": 16,
"created_at": "2023-02-23 09:03:40",
"updated_at": "2023-09-20 11:08:52",
"name": "{\"tk\":\"Telewizorlar\",\"ru\":\"\\u0422\\u0435\\u043b\\u0435\\u0432\\u0438\\u0437\\u043e\\u0440\\u044b\",\"en\":\"Televisions\"}",
"slug": "telewizorlar",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-02-23 04:02:02+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 25
},
{
"id": 17,
"created_at": "2023-02-23 09:06:16",
"updated_at": "2023-09-20 11:08:52",
"name": "{\"tk\":\"Kir \\u00fduwujy ma\\u015fynlar\",\"ru\":\"\\u0421\\u0442\\u0438\\u0440\\u0430\\u043b\\u044c\\u043d\\u044b\\u0435 \\u043c\\u0430\\u0448\\u0438\\u043d\\u044b\",\"en\":\"Washing machines\"}",
"slug": "kir-yuwujy-masynlar",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-02-23 04:04:44+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 26
},
{
"id": 18,
"created_at": "2023-02-23 09:54:15",
"updated_at": "2023-09-20 11:08:52",
"name": "{\"tk\":\"Tozan sorujylar\",\"ru\":\"\\u041f\\u044b\\u043b\\u0435\\u0441\\u043e\\u0441\\u044b\",\"en\":\"Vacuum cleaners\"}",
"slug": "tozan-sorujylar",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-02-23 04:51:35+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 27
},
{
"id": 19,
"created_at": "2023-02-23 10:17:16",
"updated_at": "2023-09-20 11:08:52",
"name": "{\"tk\":\"Suw ga\\u00fdnadyjylar\",\"ru\":\"\\u042d\\u043b\\u0435\\u043a\\u0442\\u0440\\u0438\\u0447\\u0435\\u0441\\u043a\\u0438\\u0435 \\u0447\\u0430\\u0439\\u043d\\u0438\\u043a\\u0438\",\"en\":\"Electric kettles\"}",
"slug": "suw-gaynadyjylar",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-02-23 05:14:31+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 18
},
{
"id": 20,
"created_at": "2023-02-23 10:51:20",
"updated_at": "2023-09-18 23:48:10",
"name": "{\"tk\":\"Sa\\u00e7 \\u015fekillendirijiler\",\"ru\":\"\\u041f\\u043b\\u043e\\u0439\\u043a\\u0438, \\u0441\\u0442\\u0430\\u0439\\u043b\\u0435\\u0440\\u044b, \\u0449\\u0438\\u043f\\u0446\\u044b\",\"en\":\"Curling irons, stylers, tongs\"}",
"slug": "curling-irons-stylers-tongs",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-02-23 05:49:27+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 28
},
{
"id": 21,
"created_at": "2023-02-23 10:57:47",
"updated_at": "2023-09-20 11:08:52",
"name": "{\"tk\":\"Elektrobritwalar\",\"ru\":\"\\u042d\\u043b\\u0435\\u043a\\u0442\\u0440\\u043e\\u0431\\u0440\\u0438\\u0442\\u0432\\u044b\",\"en\":\"Electric shavers\"}",
"slug": "electric-shavers",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-02-23 05:56:55+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 19
},
{
"id": 22,
"created_at": "2023-02-23 17:27:43",
"updated_at": "2023-09-18 23:48:10",
"name": "{\"tk\":\"Wafel, K\\u00f6ke, \\u00c7\\u00f6rek bi\\u015firijiler\",\"ru\":\"\\u0412\\u0430\\u0444\\u0435\\u043b\\u044c\\u043d\\u0438\\u0446\\u0430 \\u0438 \\u0425\\u043b\\u0435\\u0431\\u043e\\u043f\\u0435\\u0447\\u043a\\u0438\",\"en\":\"Waffle Maker & Bread Makers\"}",
"slug": "waffle-maker-bread-makers",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-02-23 12:14:09+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 29
},
{
"id": 23,
"created_at": "2023-02-23 17:51:50",
"updated_at": "2023-09-18 23:48:10",
"name": "{\"tk\":\"Tosterler\",\"ru\":\"\\u0422\\u043e\\u0441\\u0442\\u0435\\u0440\\u044b\",\"en\":\"Toasters\"}",
"slug": "toasters",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-02-23 12:50:58+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 30
},
{
"id": 24,
"created_at": "2023-02-27 15:29:38",
"updated_at": "2023-09-18 23:48:10",
"name": "{\"tk\":\"Mikrotolkunly Pe\\u00e7\",\"ru\":\"\\u041c\\u0438\\u043a\\u0440\\u043e\\u0432\\u043e\\u043b\\u043d\\u043e\\u0432\\u044b\\u0435 \\u041f\\u0435\\u0447\\u0438\",\"en\":\"Microwaves\"}",
"slug": "microwaves",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-02-27 10:28:57+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 31
},
{
"id": 25,
"created_at": "2023-02-27 16:47:46",
"updated_at": "2023-09-18 23:48:00",
"name": "{\"tk\":\"A\\u015fhana pe\\u00e7ler\",\"ru\":\"\\u0414\\u0443\\u0445\\u043e\\u0432\\u044b\\u0435 \\u0448\\u043a\\u0430\\u0444\\u044b\",\"en\":\"Ovens\"}",
"slug": "ovens",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-02-27 11:46:42+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 32
},
{
"id": 26,
"created_at": "2023-03-02 11:18:07",
"updated_at": "2023-09-18 23:48:00",
"name": "{\"tk\":\"Kofe Ma\\u015fyn we \\u00dcweyji\",\"ru\":\"\\u041a\\u043e\\u0444\\u0435\\u043c\\u0430\\u0448\\u0438\\u043d\\u044b \\u0438 K\\u043e\\u0444\\u0435\\u043c\\u043e\\u043b\\u043a\\u0438\",\"en\":\"Coffee machines and grinders\"}",
"slug": "coffee-machines-and-grinders",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-03-02 06:17:31+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 33
},
{
"id": 27,
"created_at": "2023-03-13 15:53:11",
"updated_at": "2023-09-18 23:48:00",
"name": "{\"tk\":\"A\\u015fhana enjamlary\",\"ru\":\"\\u041a\\u0443\\u0445\\u043e\\u043d\\u043d\\u0430\\u044f \\u0443\\u0442\\u0432\\u0430\\u0440\\u044c\",\"en\":\"Kitchenware\"}",
"slug": "ashana-enjamlary",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-03-13 10:52:35+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 34
},
{
"id": 28,
"created_at": "2023-03-14 16:07:32",
"updated_at": "2023-09-20 11:08:52",
"name": "{\"tk\":\"Kitaplar\",\"ru\":\"\\u041a\\u043d\\u0438\\u0433\\u0438\",\"en\":\"Books\"}",
"slug": "books",
"description": "{\"ru\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-03-14 11:06:18+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 16
},
{
"id": 29,
"created_at": "2023-04-05 10:21:02",
"updated_at": "2023-09-20 11:09:07",
"name": "{\"tk\":\"ARDESTO\",\"ru\":\"ARDESTO\",\"en\":\"ARDESTO\"}",
"slug": "ardesto",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-04-05 05:20:31+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 14
},
{
"id": 30,
"created_at": "2023-04-05 16:41:15",
"updated_at": "2023-09-18 23:48:00",
"name": "{\"tk\":\"Tereziler\",\"ru\":\"\\u0412\\u0435\\u0441\\u044b\",\"en\":\"Scales\"}",
"slug": "tereziler",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-04-05 11:40:00+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 35
},
{
"id": 31,
"created_at": "2023-04-11 10:24:11",
"updated_at": "2023-09-18 23:48:00",
"name": "{\"tk\":\"Asia Tech\",\"ru\":\"Asia Tech\",\"en\":\"Asia Tech\"}",
"slug": "asia-tech",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-04-11 05:23:01+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 36
},
{
"id": 32,
"created_at": "2023-04-27 09:43:52",
"updated_at": "2023-09-18 23:48:00",
"name": "{\"tk\":\"Gurlu\\u015fyk harytlary\",\"ru\":\"\\u0421\\u0442\\u0440\\u043e\\u0438\\u0442\\u0435\\u043b\\u044c\\u043d\\u044b\\u0435 \\u043c\\u0430\\u0442\\u0435\\u0440\\u0438\\u0430\\u043b\\u044b\",\"en\":\"Construction materiales\"}",
"slug": "construction-materiales",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-04-27 04:42:43+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 37
},
{
"id": 33,
"created_at": "2023-05-03 15:04:12",
"updated_at": "2023-09-18 23:48:00",
"name": "{\"tk\":\"Mi\",\"ru\":\"Mi\",\"en\":\"Mi\"}",
"slug": "mi",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-05-03 10:03:15+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 38
},
{
"id": 34,
"created_at": "2023-05-08 17:44:44",
"updated_at": "2023-09-20 11:08:52",
"name": "{\"tk\":\"Kondisionerler\",\"ru\":\"\\u041a\\u043e\\u043d\\u0434\\u0438\\u0446\\u0438\\u043e\\u043d\\u0435\\u0440\\u044b\",\"en\":\"Air conditioners\"}",
"slug": "air-conditioners",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-05-08 12:44:03+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 15
},
{
"id": 35,
"created_at": "2023-05-17 17:56:43",
"updated_at": "2023-09-18 23:48:00",
"name": "{\"tk\":\"Holodilnikler\",\"ru\":\"\\u0425\\u043e\\u043b\\u043e\\u0434\\u0438\\u043b\\u044c\\u043d\\u0438\\u043a\\u0438\",\"en\":\"Fridges\"}",
"slug": "fridges",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-05-17 12:56:07+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 39
},
{
"id": 36,
"created_at": "2023-05-23 16:14:22",
"updated_at": "2023-09-20 11:09:07",
"name": "{\"tk\":\"\\u00ddAKYNDAR\",\"ru\":\"\\u00ddAKYNDAR\",\"en\":\"\\u00ddAKYNDAR\"}",
"slug": "yakyndar",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-05-23 11:13:46+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 11
},
{
"id": 37,
"created_at": "2023-05-24 10:58:43",
"updated_at": "2023-09-18 23:48:00",
"name": "{\"tk\":\"Bo\\u00fdler\",\"ru\":\"\\u0411\\u043e\\u0439\\u043b\\u0435\\u0440\",\"en\":\"Boiler\"}",
"slug": "boiler",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-05-24 05:57:42+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 40
},
{
"id": 38,
"created_at": "2023-05-30 14:32:38",
"updated_at": "2023-09-18 23:48:00",
"name": "{\"tk\":\"Bezeg market\",\"ru\":\"\\u0411\\u0435\\u0437\\u0435\\u0433 \\u043c\\u0430\\u0440\\u043a\\u0435\\u0442\",\"en\":\"Bezeg market\"}",
"slug": "howuz",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-05-30 09:31:44+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 41
},
{
"id": 39,
"created_at": "2023-06-04 15:38:56",
"updated_at": "2023-09-18 23:37:03",
"name": "{\"tk\":\"Fen\",\"ru\":\"\\u0424\\u0435\\u043d\",\"en\":\"Hair dryer\"}",
"slug": "fen",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-06-04 10:37:45+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 42
},
{
"id": 40,
"created_at": "2023-06-07 16:57:53",
"updated_at": "2023-09-20 11:09:07",
"name": "{\"tk\":\"Mannol-Turkmenistan\",\"ru\":\"Mannol-Turkmenistan\",\"en\":\"Mannol-Turkmenistan\"}",
"slug": "mannol-turkmenistan",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-06-07 11:56:47+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 12
},
{
"id": 41,
"created_at": "2023-06-16 16:02:07",
"updated_at": "2023-09-20 11:09:07",
"name": "{\"tk\":\"Zy\\u00fdada Market\",\"ru\":\"Zy\\u00fdada Market\",\"en\":\"Zy\\u00fdada Market\"}",
"slug": "zyyada-market",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-06-16 11:01:55+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 10
},
{
"id": 42,
"created_at": "2023-06-20 11:34:54",
"updated_at": "2023-09-20 11:09:07",
"name": "{\"tk\":\"Tehnopark\",\"ru\":\"Tehnopark\",\"en\":\"Tehnopark\"}",
"slug": "tehnopark",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-06-20 06:34:35+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 13
},
{
"id": 43,
"created_at": "2023-06-26 16:35:14",
"updated_at": "2023-09-20 11:09:07",
"name": "{\"tk\":\"Akylly sagatlar we fitnes bilezikleri\",\"ru\":\"\\u0423\\u043c\\u043d\\u044b\\u0435 \\u0447\\u0430\\u0441\\u044b \\u0438 \\u0444\\u0438\\u0442\\u043d\\u0435\\u0441-\\u0431\\u0440\\u0430\\u0441\\u043b\\u0435\\u0442\\u044b\",\"en\":\"Smart watches and fitness bracelets\"}",
"slug": "akylly-sagatlar-we-fitnes-bilezikleri",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-06-26 11:33:29+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 9
},
{
"id": 44,
"created_at": "2023-06-27 20:47:04",
"updated_at": "2023-09-20 11:09:07",
"name": "{\"tk\":\"Nau\\u015fnik\",\"ru\":\"\\u041d\\u0430\\u0443\\u0448\\u043d\\u0438\\u043a\\u0438\",\"en\":\"Headphones\"}",
"slug": "headphones",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-06-27 15:46:07+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 6
},
{
"id": 45,
"created_at": "2023-07-04 15:15:09",
"updated_at": "2023-09-18 23:37:03",
"name": "{\"tk\":\"Durmu\\u015f a\\u00fdakgap\",\"ru\":\"Durmu\\u015f a\\u00fdakgap\",\"en\":\"Durmu\\u015f a\\u00fdakgap\"}",
"slug": "durmus-ayakgap",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-07-04 10:14:36+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 44
},
{
"id": 46,
"created_at": "2023-07-13 10:32:48",
"updated_at": "2023-09-20 11:09:07",
"name": "{\"tk\":\"Howuz\",\"ru\":\"\\u0411\\u0430\\u0441\\u0441\\u0435\\u0439\\u043d\",\"en\":\"Pool\"}",
"slug": "pool",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-07-13 05:32:13+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 8
},
{
"id": 47,
"created_at": "2023-07-25 10:14:45",
"updated_at": "2023-09-18 23:37:03",
"name": "{\"tk\":\"Amatly kosmetika\",\"ru\":\"Amatly kosmetika\",\"en\":\"Amatly kosmetika\"}",
"slug": "amatly-kosmetika",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-07-25 05:14:02+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 45
},
{
"id": 48,
"created_at": "2023-07-25 17:36:30",
"updated_at": "2023-09-18 23:37:03",
"name": "{\"tk\":\"Ho\\u015fal\",\"ru\":\"Ho\\u015fal\",\"en\":\"Ho\\u015fal\"}",
"slug": "hosal",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-07-25 12:36:07+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 46
},
{
"id": 49,
"created_at": "2023-08-01 09:07:30",
"updated_at": "2023-09-18 23:37:03",
"name": "{\"tk\":\"Nusga haly\",\"ru\":\"Nusga haly\",\"en\":\"Nusga haly\"}",
"slug": "nusga-haly",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-08-01 04:07:08+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 47
},
{
"id": 51,
"created_at": "2023-08-14 16:31:13",
"updated_at": "2023-09-18 23:37:03",
"name": "{\"tk\":\"KASPIAN\",\"ru\":\"KASPIAN\",\"en\":\"KASPIAN\"}",
"slug": "kaspian",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-08-14 11:30:54+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 48
},
{
"id": 52,
"created_at": "2023-09-02 13:28:40",
"updated_at": "2024-01-17 09:33:37",
"name": "{\"tk\":\"Smart Elektronika\",\"ru\":\"Smart Elektronika\",\"en\":\"Smart Elektronika\"}",
"slug": "web-ulgam-electronics",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-09-02 08:28:06+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 2
},
{
"id": 53,
"created_at": "2023-09-18 23:34:28",
"updated_at": "2023-09-20 11:09:07",
"name": "{\"tk\":\"Komp\\u00fduter harytlary\",\"ru\":\"\\u041a\\u043e\\u043c\\u043f\\u044c\\u044e\\u0442\\u0435\\u0440\\u043d\\u044b\\u0435 \\u0442\\u043e\\u0432\\u0430\\u0440\\u044b\",\"en\":\"Computer products\"}",
"slug": "kompyuter-harytlary",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-09-18 18:33:30+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 1
},
{
"id": 54,
"created_at": "2023-10-09 11:02:22",
"updated_at": "2023-10-09 11:02:22",
"name": "{\"tk\":\"Opt tm\",\"ru\":\"Opt tm\",\"en\":\"Opt tm\"}",
"slug": "opt-tm",
"description": "{\"en\":null}",
"type": "manual",
"sort": null,
"match_conditions": null,
"published_at": "2023-10-09 06:01:46+00",
"seo_title": null,
"seo_description": null,
"shown_on_homescreen": true,
"sort_order": 49
}
]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,42 +0,0 @@
[
{
"id": 1,
"created_at": "2022-05-25 21:22:29",
"updated_at": "2024-02-21 15:46:46",
"name": "Türkmenpoçta",
"code": "ammar",
"description": null,
"email": "postshop2023@gmail.com",
"street_address": "ş. Aşgabat köçe Petrozowodskoý 6",
"street_address_plus": null,
"zipcode": "744000",
"city": "Aşgabat",
"phone_number": "+99365728952",
"priority": 0,
"latitude": 255.00000,
"longitude": 255.00000,
"is_default": false,
"country_id": 223,
"channel_id": 1
},
{
"id": 3,
"created_at": "2024-01-30 17:29:55",
"updated_at": "2024-02-21 15:46:46",
"name": "Dükan",
"code": "Dükan",
"description": null,
"email": "postshop2023@gmail.com",
"street_address": "B.Annanow 39A",
"street_address_plus": null,
"zipcode": "744000",
"city": "Ashgabat",
"phone_number": "+99365728952",
"priority": 0,
"latitude": null,
"longitude": null,
"is_default": false,
"country_id": null,
"channel_id": 1
}
]

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -1,312 +0,0 @@
[
{
"role_id": 1,
"model_type": "App\\Models\\User",
"model_id": 1
},
{
"role_id": 1,
"model_type": "App\\Models\\User",
"model_id": 2
},
{
"role_id": 1,
"model_type": "App\\Models\\User",
"model_id": 59
},
{
"role_id": 1,
"model_type": "App\\Models\\User",
"model_id": 60
},
{
"role_id": 1,
"model_type": "App\\Models\\User",
"model_id": 388
},
{
"role_id": 1,
"model_type": "App\\Models\\User",
"model_id": 2154
},
{
"role_id": 1,
"model_type": "App\\Models\\User",
"model_id": 2158
},
{
"role_id": 1,
"model_type": "App\\Models\\User",
"model_id": 2356
},
{
"role_id": 1,
"model_type": "App\\Models\\User",
"model_id": 7676
},
{
"role_id": 2,
"model_type": "App\\Models\\User",
"model_id": 786
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 16
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 103
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 340
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 715
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 836
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 848
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 1025
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 1659
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 1772
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 1915
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 1916
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 1917
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 1918
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 1919
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 1925
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 1932
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 2054
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 2086
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 2260
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 2355
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 2710
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 2924
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 2962
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 3021
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 3158
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 3325
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 3448
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 3650
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 3672
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 3684
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 4149
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 4223
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 4430
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 4512
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 4879
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 5097
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 5298
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 5777
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 5945
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 6103
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 6170
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 6633
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 6717
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 7002
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 7300
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 7514
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 7539
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 7609
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 7835
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 7882
},
{
"role_id": 6,
"model_type": "App\\Models\\User",
"model_id": 8742
},
{
"role_id": 8,
"model_type": "App\\Models\\User",
"model_id": 5867
}
]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More