Commit 602b047e authored by 符宝's avatar 符宝
Browse files

初始化

parent f4cba9bf
No related merge requests found
Pipeline #18 canceled with stages
Showing with 1574 additions and 86 deletions
+1574 -86
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2
[docker-compose.yml]
indent_size = 4
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DRIVER=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"
OSS_ACCESS_KEY_ID=<Your aliyun accessKeyId, Required>
OSS_ACCESS_KEY_SECRET=<Your aliyun accessKeySecret, Required>
OSS_BUCKET=<Your oss bucket name, Required>
OSS_ENDPOINT=<Your oss endpoint domain, Required>
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
BANMA_DOMAIN="banmaerp.com"
BANMA_SESSION="1111"
BANMA_TOKEN="1111111"
* text=auto
*.blade.php diff=html
*.css diff=css
*.html diff=html
*.md diff=markdown
*.php diff=php
/.github export-ignore
CHANGELOG.md export-ignore
/node_modules
/public/hot
/public/catalog/*
/public/uploads/products/*
/storage/*.key
/storage/debugbar
/vendor
.env
.env.backup
.phpunit.result.cache
docker-compose.override.yml
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log
/.idea
/.vscode
/.htaccess
/public/zip
php:
preset: laravel
version: 8
disabled:
- no_unused_imports
finder:
not-name:
- index.php
- server.php
js:
finder:
not-name:
- webpack.mix.js
css: true
# scm
scm
## Getting started
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
## Add your files
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
## 商品管理系统
#### env文件配置
```
cd existing_repo
git remote add origin https://gitlab.jialenet.com/tech/scm.git
git branch -M main
git push -uf origin main
APP_NAME=在cas项目中cas_service表里创建的name
APP_SECRET=在cas项目中cas_service表里创建的token
CAS_HOSTNAME=cas服务的域名
CAS_REAL_HOSTS=cas服务的域名
CAS_LOGOUT_URL=https://cas服务的域名/logout
CAS_LOGOUT_REDIRECT=
CAS_URI=
CAS_ENABLE_SAML=FALSE
// 图片保存地址,public为本地,线上为aliyun
UPLOAD_IMAGE_DRIVES="public"
// 是否同步数据给banma的erp,本地建议配成0
SYNC_BANMA=0
// 需要翻译成的语言
TRANSLATE_LANGUAGES=en
// 系统内填写的产品数据默认语言
DEFAULT_LANGUAGE_CODE=en
```
## Integrate with your tools
- [ ] [Set up project integrations](https://gitlab.jialenet.com/tech/scm/-/settings/integrations)
## Collaborate with your team
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
## Test and Deploy
Use the built-in continuous integration in GitLab.
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
***
# Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
## Support
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README.
## Contributing
State if you are open to contributions and what your requirements are for accepting them.
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
## Authors and acknowledgment
Show your appreciation to those who have contributed to the project.
#### supervisor 配置
- pdm队列
```
[program:pdm_queue]
process_name=%(program_name)s
command=php /home/www/code/prodhub/artisan queue:work --queue=syncDataExport --sleep=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www
redirect_stderr=true
stdout_logfile=/tmp/pdm_queue.log
stopwaitsecs=3600
```
## License
For open source projects, say how it is licensed.
- horizon配置
```
[program:horizon]
process_name=%(program_name)s
command=php /home/www/code/prodhub/artisan horizon
autostart=true
autorestart=true
user=www
redirect_stderr=true
stdout_logfile=/var/log/horizon.log
stopwaitsecs=3600
## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
```
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Services\SSOService;
use Carbon\Carbon;
use Carbon\CarbonTimeZone;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class ApiPlatformService extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'platform:api-service {--site_id=} {--platform=}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'platform api 接口操作';
public $platform_service = [
// 'shopify' => '\App\Services\Shopify\WebhookService',
'shoplazza' => '\App\Services\Shoplazza\ApiService',
//'shoplus' => '\App\Services\Shoplus\WebhookService',
'shoplineV2' => '\App\Services\ShoplineV2\ApiService',
//'jlshop' => '\App\Services\Jlshop\OrderService',
];
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
set_time_limit(0);
$filter_site_ids = $this->option('site_id');
$platform = $this->option('platform');
if (!$filter_site_ids && !$platform) {
$this->error('请输入site_id');
return;
}
$filter_site_ids = explode(',', $filter_site_ids);
if ($platform) {
$sites = SSOService::getSites([], true, false);
} else {
$sites = SSOService::getSites(['ids' => $filter_site_ids], true, false);
}
foreach ($sites as $site_info) {
if (empty(data_get($site_info, 'auth_params')) || data_get($site_info, 'status') != 1) {
continue;
}
if ($platform && strcasecmp($site_info['type'], $platform) != 0) {
continue;
}
try {
$platform_service = data_get($this->platform_service, data_get($site_info, 'type'));
if ($platform_service && data_get($site_info, 'type')) {
$service = new $platform_service();
$params['site_info'] = $site_info;
$result = $service->metafieldsSet($params);
}
} catch (Exception $exception) {
Log::error('platform_service_error:', [
'message' => $exception->getMessage(),
'site' => $site_info,
'params' => $params,
'file' => $exception->getFile(),
'line' => $exception->getLine(),
]);
continue;
}
$this->info('平台操作metafields_set 创建完成:' . $site_info['name'] . ' site_id:' . $site_info['id']);
}
}
}
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Support\Facades\DB;
use App\Extensions\Utils;
use App\Extensions\SDK\Banma;
use App\Models\Inventory;
use App\Models\LockList;
use App\Models\OptionValue;
use App\Models\Product;
use App\Models\SelfIn;
use App\Models\SelfInRecord;
use App\Models\SiteOrderCount;
use App\Services\ProductService;
use App\Services\SSOService;
use Illuminate\Support\Facades\Log;
class ChangeSizeChartPosition extends Command
{
use DispatchesJobs;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'product:change-chart {--spu=} {--site_id=} {--position=}';
/**
* The console command description.
*
* @var string
*/
protected $description = '商品描述移动尺码表格';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$start = 0;
$limit = 1000;
$productService = new ProductService();
$site_id = $this->option('site_id') ?: 0;
$position = $this->option('position') ?: 1;
$spu = $this->option('spu') ?: '';
$site = SSOService::getSiteInfo($site_id);
if ($spu) {
$spu = explode(',', $spu);
}
do {
$products = Product::where('site_id', $site_id)
->where(function ($query) use ($spu) {
if ($spu) {
$query->whereIn('spu', $spu);
}
})
->skip($start * 1000)
->take($limit)
->get();
$update_product_spu = [];
$error_product_spu = [];
foreach ($products as $product) {
$product->description = Utils::changeSizeChartPosition($product->description, $position, data_get($site, 'language_code', 'en'));
if (empty($product->description)) {
$error_product_spu[] = $product->spu;
continue;
}
$product->save();
$update_product_spu[] = $product->spu;
if ($product->status == Product::STATUS_ONLINE) {
$productService->dispatchQueueBySite($product, 'sync');
}
}
$start++;
$this->info('站点:' . $site_id . ' 完成替换:' . ($start * $limit));
Log::info('站点:' . $site_id . ' 更新商品ID:', $update_product_spu);
Log::info('站点:' . $site_id . ' 替换失败商品SPU:', $error_product_spu);
} while ($products->count() >= $limit);
$this->info('站点:' . $site_id . ' 全部替换完成');
return true;
}
}
<?php
namespace App\Console\Commands;
use App\Models\OrderStatus;
use Illuminate\Console\Command;
use App\Extensions\SDK\Banma;
use App\Models\Order;
use App\Services\OrderService;
use App\Services\SSOService;
use App\Extensions\Utils;
use App\Models\OrderPackage;
use App\Models\OrderProduct;
use App\Models\Product;
use App\Models\ProductSku;
use App\Models\PullOrderLog;
use App\Services\OrderLockInventoryService;
use Carbon\Carbon;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
class CheckBanmaOrderStatus extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'banma:check-order-status {--page_number=} {--start_date=} {--end_date=}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'banma check-order-status';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
const STATUS_NAME = [
'已下单' => Order::ORDER_STATUS_PLACED,
'待审核' => Order::ORDER_STATUS_REVIEW,
'待发货' => Order::ORDER_STATUS_WAIT_DELIVERY,
'部分发货' => Order::ORDER_STATUS_PART_DELIVERY,
'已发货' => Order::ORDER_STATUS_DELIVERED,
'已取消' => Order::ORDER_STATUS_CANCELLED
];
const HOLD_STATUS = [
'未暂停' => ORDER::PAUSE_STATUS_NO,
'已暂停' => ORDER::PAUSE_STATUS_YES,
];
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
set_time_limit(0);
$banma = new Banma();
$page_size = 50;
$page_cache_key = 'check-banma-orders-new2';
$option_page_number = intval($this->option('page_number'));
$curr_page_number = $option_page_number ? $option_page_number : max(1, Cache::get($page_cache_key, 1) - 2);
$query = [
'PageNumber' => $curr_page_number,
'PageSize' => $page_size,
'PayStatus' => '已付款',
];
if ($this->option('start_date') && $this->option('end_date')) {
//按更新时间,补充最新数据
$query['SearchTimeStart'] = Carbon::parse($this->option('start_date'))->format('Y-m-d\TH:i:s');
$query['SearchTimeEnd'] = Carbon::parse($this->option('end_date'))->format('Y-m-d\TH:i:s');
$query['SearchTimeField'] = 'UpdateTime';
}
$retry = false;
do {
try {
$response = $banma->get0Order(['request_path' => '/v1/order', 'query' => $query], ['v1']);
$orders = data_get($response, 'Data.Orders', []);
if (data_get($response, 'error') == 1) {
sleep(2);
$retry = true;
continue;
}
foreach ($orders as $order_info) {
$order_platform_id = data_get($order_info, 'Master.OriginalOrderID');
$order_status = data_get($order_info, 'Master.Status') ? data_get(self::STATUS_NAME, $order_info['Master']['Status']) : 0;
$hold_status = data_get($order_info, 'Master.HoldStatus') ? data_get(self::HOLD_STATUS, $order_info['Master']['HoldStatus']) : 0;
$update_data = [];
if ($order_status) {
$update_data['order_status_id'] = $order_status;
}
if ($hold_status) {
$update_data['pause_status'] = Order::PAUSE_STATUS_YES;
}
if ($update_data && $order_platform_id) {
// 已发货,部分发货,已完成,部分完成 以本地为主
Order::where('platform_order_id', $order_platform_id)
->whereNotIn('order_status_id', [Order::ORDER_STATUS_DELIVERED, Order::ORDER_STATUS_FINISHED, Order::ORDER_STATUS_PART_DELIVERY, Order::ORDER_STATUS_PART_FINISHED])
->update($update_data);
}
}
if ($orders) {
if ($query['PageNumber'] % 100 == 0) {
Log::info('pull-banma-order-status-pagenumber:', ['pagenumber' => $query['PageNumber']]);
}
$query['PageNumber']++;
$curr_page_number++;
if ($page_cache_key && !$option_page_number) {
Cache::put($page_cache_key, $curr_page_number, 36000);
}
$retry = false;
}
} catch (\Throwable $th) {
$retry = true;
}
} while ((count($orders) >= $page_size || $retry));
}
}
<?php
namespace App\Console\Commands;
use App\Extensions\Es\Item;
use App\Models\Order;
use App\Models\OutStock;
use App\Models\SiteShippingCountry;
use App\Services\OrderLockInventoryService;
use App\Services\OrderService;
use Illuminate\Console\Command;
use App\Services\SSOService;
use Carbon\Carbon;
use Carbon\CarbonTimeZone;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class CheckOrderInventory extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'check-order:inventory {--order_id=}';
/**
* The console command description.
*
* @var string
*/
protected $description = '检查订单库存信息';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
set_time_limit(0);
$order_id = $this->option('order_id');
if ($order_id) {
$order_id = explode(',', $order_id);
} else {
$this->info('请输入订单id');
return false;
}
$orders = Order::whereIn('id', $order_id)->get(['id']);
$orderLockInventoryService = new OrderLockInventoryService();
foreach ($orders as $order) {
$orderLockInventoryService->checkPackageInventory('', '', $order->id);
Log::info('检查订单库存:',[$order->id]);
}
return;
}
}
<?php
namespace App\Console\Commands;
use App\Models\Option;
use App\Models\OptionDescription;
use App\Models\OptionValue;
use App\Models\OptionValueDescription;
use App\Models\ProductSkuSpec;
use App\Models\SkuSpec;
use App\Services\OptionService;
use App\Services\SkuService;
use Illuminate\Console\Command;
use App\Services\SSOService;
use Carbon\Carbon;
use Carbon\CarbonTimeZone;
use Exception;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class ClearCache extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'cache:clear {--cache_key=}';
/**
* The console command description.
*
* @var string
*/
protected $description = '清理cache缓存信息';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$cache_key = $this->option('cache_key');
if ($cache_key) {
Cache::forget($cache_key);
}
$this->info('已经整理完cache:' . $cache_key);
}
}
<?php
namespace App\Console\Commands;
use App\Models\Item;
use App\Models\Product;
use App\Services\ItemService;
use App\Services\ProductService;
use Illuminate\Console\Command;
class ClearItemSizeChart extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'item:clear-size-chart {--spu=} {--id=}';
/**
* The console command description.
*
* @var string
*/
protected $description = '清理产品描述中的table尺码信息';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$spus = $this->option('spu');
$ids = $this->option('id');
if (!$spus && !$ids) {
$this->error('请输入spu或者产品id');
return;
}
return;
$service = new ItemService();
$offset = 0;
$limit = 5000;
if ($ids) {
$ids = explode(',', $ids);
}
if ($spus) {
$spus = explode(',', $spus);
}
do {
$items = Item::where(function ($query) use ($ids, $spus) {
if ($ids) {
$query->whereIn('id', $ids);
}
if ($spus) {
$query->whereIn('spu', $spus);
}
return $query;
})
->offset($offset)
->limit($limit)
->get(['id'])->toArray();
foreach ($items as $val) {
$service->filterSizeChart($val['id']);
}
$offset += $limit;
$this->info('已经清理描述中的table尺码信息:offset=' . $offset);
} while (count($items) == $limit);
$this->info('已经清理描述中的table尺码信息:spu=' . implode(',', $spus ?: []), ' id=' . implode(',', $ids ?: []));
}
}
<?php
namespace App\Console\Commands;
use App\Models\Option;
use App\Models\OptionDescription;
use App\Models\OptionValue;
use App\Models\OptionValueDescription;
use App\Models\ProductSkuSpec;
use App\Models\SkuSpec;
use App\Services\OptionService;
use App\Services\SkuService;
use Illuminate\Console\Command;
use App\Services\SSOService;
use Carbon\Carbon;
use Carbon\CarbonTimeZone;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class ClearOptions extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'option:clear {--option_id=}';
/**
* The console command description.
*
* @var string
*/
protected $description = '合并option,option_value';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
set_time_limit(0);
$source_option = Option::where('id', '>', 0)->orderBy('id', 'ASC')->get()->toArray();
foreach ($source_option as $option) {
// 清理相同的option问题
$same_options = Option::where('id', '!=', $option['id'])
->where('name', $option['name'])
->orderBy('id', 'ASC')
->where('id', '>', 2)
->get(['id'])->toArray();
foreach ($same_options as $same_option) {
$offset = 0;
$limit = 5000;
do {
$same_option_values = OptionValue::where('option_id', $same_option['id'])
->offset($offset)
->limit($limit)
->get()->toArray();
$update_item_ids = [];
$update_product_ids = [];
foreach ($same_option_values as $same_option_value) {
// 同option,没有option_value则新增
$old_option_value = OptionValue::firstOrCreate(['option_id' => $option['id'], 'name' => $same_option_value['name']]);
DB::transaction(function () use ($same_option, $old_option_value, $option, $same_option_value) {
// SkuSpec::where('option_value_id', $same_option_value['id'])
// ->where('option_id', $same_option_value['option_id'])
// ->update(['option_value_id' => $old_option_value->id, 'option_id' => $old_option_value->option_id]);
// ProductSkuSpec::where('option_value_id', $same_option_value['id'])
// ->where('option_id', $same_option_value['option_id'])
// ->update(['option_value_id' => $old_option_value->id, 'option_id' => $old_option_value->option_id]);
//需要清理的sku_spec
if (!in_array($same_option['id'], [Option::SIZE_OPTION_ID, Option::COLOR_OPTION_ID])) {
// 清理多余的option ,option_value 数据
//OptionValue::where('option_id', $same_option['id'])->delete();
// OptionValueDescription::where('option_value_id', $same_option_value['id'])->delete();
Log::info('需要删除的 option_id:', $same_option);
//Option::where('id', $same_option['id'])->delete();
//OptionDescription::where('option_id', $same_option['id'])->delete();
Option::where('id', $same_option['id'])->update(['status' => 0]);
OptionValue::where('option_id', $same_option['id'])->update(['status' => 0]);
} else {
Log::info('异常清理 不执行option_id:', $same_option);
$this->info('异常清理到option_id:' . $same_option['id'] . ' 不执行删除操作');
}
}, 3);
}
$update_item_ids && Log::info('需要更新的sku_specs item_id:', $update_item_ids);
$update_product_ids && Log::info('需要更新的product_sku_spec product_id:', $update_product_ids);
$offset += $limit;
} while (count($same_option_values) == $limit);
}
$offset = 0;
$limit = 5000;
// 清理option内 option_value 存在多个相同的问题 当前只清理上次添加错误的,后续再全部清理
do {
$option_values = OptionValue::where('option_id', $option['id'])
->offset($offset)
->limit($limit)
->selectRaw('name,min(id) as id')
->groupBy('name')->get()->toArray();
foreach ($option_values as $option_value) {
$same_option_values = OptionValue::where('option_id', $option['id'])
->where('id', '!=', $option_value['id'])
->where('name', $option_value['name'])
->get(['id'])->toArray();
$same_option_value_ids = array_column($same_option_values, 'id');
if ($same_option_value_ids) {
$this->info('清理option_value:' . $option_value['id']);
DB::transaction(function () use ($same_option_value_ids, $option, $option_value) {
// SkuSpec::whereIn('option_value_id', $same_option_value_ids)->where('option_id', $option['id'])->update(['option_value_id' => $option_value['id']]);
// ProductSkuSpec::whereIn('option_value_id', $same_option_value_ids)->where('option_id', $option['id'])->update(['option_value_id' => $option_value['id']]);
// OptionValue::whereIn('id', $same_option_value_ids)->delete();
// OptionValueDescription::whereIn('option_value_id', $same_option_value_ids)->delete();
OptionValue::whereIn('id', $same_option_value_ids)->update(['status' => 0]);
}, 3);
}
}
$offset += $limit;
} while (count($option_values) == $limit);
}
$this->info('已经整理完option_value');
}
}
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Services\SSOService;
use Carbon\Carbon;
use Carbon\CarbonTimeZone;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class ClearPlatformDuplicateProduct extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'platform:clear-product {--site_id=}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'platform clear-duplicate-product';
public $platform_service = [
'shopify' => '\App\Services\Shopify\ProductService',
'shoplazza' => '\App\Services\Shoplazza\ProductService',
'shoplus' => '\App\Services\Shoplus\ProductService',
'shoplineV2' => '\App\Services\ShoplineV2\ProductService',
//'jlshop' => '\App\Services\Jlshop\OrderService',
];
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
set_time_limit(0);
$filter_site_ids = $this->option('site_id');
if ($filter_site_ids) {
$filter_site_ids = explode(',', $filter_site_ids);
}
$sites = SSOService::getSites(['ids' => $filter_site_ids]);
foreach ($sites as $site_info) {
if (empty(data_get($site_info, 'auth_params')) || data_get($site_info, 'status') != 1) {
continue;
}
try {
$platform_service = data_get($this->platform_service, data_get($site_info, 'type'));
if ($platform_service && data_get($site_info, 'type')) {
$service = new $platform_service();
$service->clearDuplicate($site_info['id']);
}
} catch (Exception $exception) {
Log::error('platform_pull_product:', [
'message' => $exception->getMessage(),
'site' => $site_info,
'file' => $exception->getFile(),
'line' => $exception->getLine(),
]);
continue;
}
$this->info('已经拉取完站点product:' . $site_info['name'] . ' site_id:' . $site_info['id']);
}
}
}
<?php
namespace App\Console\Commands;
use App\Models\Product;
use App\Services\ProductService;
use Illuminate\Console\Command;
class ClearProductSizeChart extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'product:clear-size-chart {--site_id=} {--spu=}';
/**
* The console command description.
*
* @var string
*/
protected $description = '清理商品描述中的table尺码信息';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$site_id = $this->option('site_id');
$spu = $this->option('spu');
if (!$site_id) {
$this->error('请输入站点site_id');
return;
}
$service = new ProductService();
$offset = 0;
$limit = 5000;
if ($spu) {
$spu = explode(',', $spu);
}
do {
$products = Product::where(function ($query) use ($spu) {
if ($spu) {
$query->whereIn('spu', $spu);
}
return $query;
})
->where('site_id', $site_id)
->offset($offset)
->limit($limit)
->get(['id', 'item_id', 'spu'])->toArray();
foreach ($products as $product) {
$service->filterSizeChart($product['id']);
}
$offset += $limit;
$this->info('已经清理描述中的table尺码信息:offset=' . $offset);
} while (count($products) == $limit);
$this->info('已经清理描述中的table尺码信息:site_id=' . $site_id, ' spu=' . implode(',', $spu ?: []));
}
}
<?php
namespace App\Console\Commands;
use App\Extensions\Utils;
use App\Models\SiteCategory;
use App\Services\SiteCategoryService;
use DB;
use Illuminate\Console\Command;
class CopySiteCategories extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'copy:site-categories {--from_site_id=} {--to_site_id=}';
/**
* The console command description.
*
* @var string
*/
protected $description = '复制站点site-categories数据';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$from_site_id = $this->option('from_site_id');
$to_site_id = $this->option('to_site_id');
if (empty($from_site_id) || empty($to_site_id)) {
$this->error('请输出相关站点from_site_id ,to_site_id');
return true;
}
$site_category = SiteCategory::where('site_id', $from_site_id)->get()->toArray();
//dd($site_category);
$this->getTree($site_category, 0, $to_site_id);
$this->info('执行完成');
}
public function getTree($data, $pid = 0, $to_site_id = 0)
{
static $list = [];
foreach ($data as $key => $value) {
if ($value['parent_id'] == $pid) {
$parent_id = $pid;
$name = data_get($value, 'name', '');
$id = data_get($value, 'id');
if($parent_id!=0){
$parent_id=data_get($list,$parent_id);
}
$site_category_result = SiteCategory::updateOrCreate(
['name' => $name, 'site_id' => $to_site_id, 'parent_id' => $parent_id],
['google_category_id' => data_get($value, 'google_category_id',0), 'platform_id'=>data_get($value,'platform_id',0)]
);
$list[$id] = $site_category_result->id;
$this->getTree($data, $id, $to_site_id);
}
}
return $list;
}
}
<?php
namespace App\Console\Commands;
use App\Extensions\Es\Product as EsProduct;
use App\Extensions\Utils;
use App\Models\Product;
use App\Models\ProductSku;
use App\Models\ProductSkuSpec;
use App\Models\ProductToImage;
use App\Models\ProductToSiteCategory;
use App\Models\ProductToSiteTag;
use App\Models\SiteCategory;
use App\Models\SiteTag;
use App\Services\ProductService;
use App\Services\SiteCategoryService;
use App\Services\SSOService;
use DB;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
class CopySiteProducts extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'copy:site-products {--from_site_id=} {--to_site_id=} {--max_platform_id==}';
/**
* The console command description.
*
* @var string
*/
protected $description = '复制站点site-products数据(包括site_tags,site_categories)';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
set_time_limit(0);
$from_site_id = $this->option('from_site_id');
$to_site_id = $this->option('to_site_id');
$max_platform_id = $this->option('max_platform_id');
if (empty($from_site_id) || empty($to_site_id)) {
$this->error('请输出相关站点from_site_id ,to_site_id');
return false;
}
$sites = SSOService::getSites();
if ($sites) {
$sites = array_column($sites, null, 'id');
}
$site_category_ids = $this->copySiteCategory($from_site_id, $to_site_id);
$site_tag_ids = $this->copySiteCateTag($from_site_id, $to_site_id);
$from_site_type = data_get($sites, $from_site_id . '.type');
$to_site_type = data_get($sites, $to_site_id . '.type');
// 只支持同站点type之间的复制 根据业务逻辑可以调整不同type之间复制
if ($from_site_type != $to_site_type) {
$this->error('当前站点type不一致');
}
if (!$max_platform_id && $from_site_type == 'jpshop') {
$this->error('jpshop复制商品必须,必须设置当前最大max_platform_id');
return false;
}
$page = 1;
$size = 100;
$productPublicService = (new ProductService());
$max_platform_id = 1056;
$exclude_item_id = [2293, 2198, 2194, 2130, 107];
do {
$offset = max($size * ($page - 1), 0);
$site_product = Product::with('tags', 'categories', 'images', 'skus')
->where('site_id', $from_site_id)
->orderBy('id', 'DESC')
->offset($offset)
->limit($size)
->get()
->toArray();
foreach ($site_product as $product) {
// 创建prouducts
// max platform_id是to_site_from 平台的最大id
// 超过max_platform_id说明是源站点最近同步的,目标站点还没有同步过 不能直接使用源站的platform_id
$product_id = data_get($product, 'id', 0);
$platform_id = data_get($product, 'platform_id', 0);
$product['site_id'] = $to_site_id;
$product['banma_id'] = null;
if (in_array(data_get($product, 'item_id'), $exclude_item_id)) {
continue;
}
// 只有日本站前台页面可以直接复制数据库,其他站点都需要异步请求接口更新
if ($platform_id && $platform_id <= $max_platform_id && $to_site_type == $from_site_type && $to_site_type == 'jpshop') {
$product['platform_id'] = $platform_id;
} else {
$product['status'] = Product::STATUS_OFFLINE;
$product['publish_status'] = Product::PUBLISH_STATUS_NO;
$product['platform_id'] = null;
}
$productModel = Product::updateOrCreate(
['item_id' => data_get($product, 'item_id', 0), 'site_id' => $to_site_id],
$product
);
$to_product_id = $productModel->id;
// 创建images
$product_images = ProductToImage::where('product_id', $product_id)->get()->toArray();
foreach ($product_images as $image_value) {
$productToImage = ProductToImage::firstOrCreate(
['product_id' => $to_product_id, 'image_id' => data_get($image_value, 'image_id', 0)],
['product_id' => $to_product_id, 'image_id' => data_get($image_value, 'image_id', 0)],
);
}
// 创建tag标签
$product_tags = ProductToSiteTag::where('product_id', $product_id)->get()->toArray();
foreach ($product_tags as $tag_value) {
$tag_id = data_get($site_tag_ids, data_get($tag_value, 'site_tag_id'));
if ($tag_id) {
ProductToSiteTag::firstOrCreate(
['product_id' => $to_product_id, 'site_tag_id' => $tag_id],
['product_id' => $to_product_id, 'site_tag_id' => $tag_id]
);
}
}
// 创建category
$product_category = ProductToSiteCategory::where('product_id', $product_id)->get()->toArray();
foreach ($product_category as $category_value) {
$site_category_id = data_get($site_category_ids, data_get($category_value, 'site_category_id'));
if ($site_category_id) {
ProductToSiteCategory::firstOrCreate(
['product_id' => $to_product_id, 'site_category_id' => $site_category_id],
['product_id' => $to_product_id, 'site_category_id' => $site_category_id]
);
}
}
// 创建sku
$product_sku = ProductSku::where('product_id', $product_id)->get()->toArray();
foreach ($product_sku as $sku_value) {
$sku = data_get($sku_value, 'sku');
$product_sku_id = data_get($sku_value, 'id');
$sku_value['product_id'] = $to_product_id;
unset($sku_value['banma_sku_id']);
if ($sku) {
$productSkuResult = ProductSku::updateOrCreate(
['product_id' => $to_product_id, 'sku' => $sku],
$sku_value
);
$product_sku_result_id = data_get($productSkuResult, 'id');
if ($product_sku_result_id) {
$product_sku_spec = ProductSkuSpec::where('product_sku_id', $product_sku_id)->get()->toArray();
foreach ($product_sku_spec as $sku_spec) {
unset($sku_spec['product_sku_id']);
if ($sku_spec) {
$productSkuSpecResult = ProductSkuSpec::firstOrCreate(
[
'product_sku_id' => $product_sku_result_id,
'option_id' => data_get($sku_spec, 'option_id', 0),
'option_value_id' => data_get($sku_spec, 'option_value_id', 0)
],
[
'product_sku_id' => $product_sku_result_id,
'option_id' => data_get($sku_spec, 'option_id', 0),
'option_value_id' => data_get($sku_spec, 'option_value_id', 0),
'spec_sku_id' => data_get($sku_spec, 'spec_sku_id', 0)
],
);
}
}
}
}
}
EsProduct::refresh($to_product_id);
}
$this->info('完成page:' . $page);
$page++;
} while (count($site_product) >= $size);
$this->info('执行完成');
return true;
}
/**
*复制站点类目
*
*/
private function copySiteCategory($from_site_id, $to_site_id = 0)
{
$site_category = SiteCategory::where('site_id', $from_site_id)->get()->toArray();
return $this->getTree($site_category, 0, $to_site_id);
}
/**
* 复制站点标签
*/
private function copySiteCateTag($from_site_id, $to_site_id = 0)
{
$site_tags = SiteTag::where('site_id', $from_site_id)->get()->toArray();
$list = [];
foreach ($site_tags as $key => $value) {
$id = data_get($value, 'id', 0);
$siteTagResult = SiteTag::updateOrCreate(
['name' => data_get($value, 'name', ''), 'site_id' => $to_site_id],
['create_user_id' => data_get($value, 'create_user_id', 0), 'update_user_id' => data_get($value, 'update_user_id', 0)]
);
$list[$id] = data_get($siteTagResult, 'id', 0);
}
return $list;
}
private function getTree($data, $pid = 0, $to_site_id = 0)
{
static $list = [];
foreach ($data as $key => $value) {
if ($value['parent_id'] == $pid) {
$parent_id = $pid;
$name = data_get($value, 'name', '');
$id = data_get($value, 'id');
if ($parent_id != 0) {
$parent_id = data_get($list, $parent_id);
}
$site_category_result = SiteCategory::updateOrCreate(
['name' => $name, 'site_id' => $to_site_id, 'parent_id' => $parent_id],
['google_category_id' => data_get($value, 'google_category_id', 0), 'platform_id' => data_get($value, 'platform_id', 0)]
);
$list[$id] = $site_category_result->id;
$this->getTree($data, $id, $to_site_id);
}
}
return $list;
}
}
<?php
namespace App\Console\Commands;
use App\Extensions\Es\Item as EsItem;
use Illuminate\Console\Command;
class DeleteEsItem extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'es:delete-item {--ids=}';
/**
* The console command description.
*
* @var string
*/
protected $description = '根据id删除item es 缓存信息';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$esItem = new esItem;
$ids = $this->option('ids');
if (empty($ids)) {
return false;
}
$ids = explode(',', $ids);
foreach ($ids as $id) {
$id && $esItem->destory($id);
}
}
}
<?php
namespace App\Console\Commands;
use App\Extensions\Es\Product as EsProduct;
use Illuminate\Console\Command;
class DeleteEsProduct extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'es:delete-product {--ids=}';
/**
* The console command description.
*
* @var string
*/
protected $description = '根据id删除product es 缓存信息';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$esProduct = new EsProduct();
$ids = $this->option('ids');
if (empty($ids)) {
return false;
}
$ids = explode(',', $ids);
foreach ($ids as $id) {
$id && $esProduct->destory($id);
}
}
}
<?php
namespace App\Console\Commands;
use App\Models\Image;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use PhpParser\Node\Stmt\TryCatch;
class DeleteOrderLabel extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'order-label-pdf:delete';
/**
* The console command description.
*
* @var string
*/
protected $description = '清理本地面单数据';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$exist_files = Storage::disk('local_label')->files();
$delete_file = [];
try {
foreach ($exist_files as $file_path) {
$last_time = Storage::disk('local_label')->lastModified($file_path);
$time_difference = time() - $last_time;
// 大于四天前的数据清理
if ($time_difference > (4 * 24 * 60 * 60)) {
$delete_file[] = $file_path;
}
}
if ($delete_file) {
Storage::disk('local_label')->delete($delete_file);
}
} catch (\Throwable $th) {
Log::error('本地面单pdf数据清理异常:', ['error' => $th->getMessage()]);
return false;
}
$this->info('本地面单pdf数据清理完成');
return true;
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment