sierratecnologia / market
market
Fund package maintenance!
ricasolucoes
ricasolucoes.com.br/open-source/support-us
Installs: 5
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
pkg:composer/sierratecnologia/market
Requires
- php: ^7.2|^8.0
- sierratecnologia/bancario: ^0.4.0
- sierratecnologia/crypto: ^0.4.0
- sierratecnologia/locaravel: ^0.4.0
- sierratecnologia/media-manager: ^0.4.0
- sierratecnologia/muleta: ^0.4.0
- sierratecnologia/payment-laravel: ^0.3.0 | ^0.4.0
- sierratecnologia/pedreiro: ^0.4.0
This package is auto-updated.
Last update: 2025-11-06 04:45:23 UTC
README
SierraTecnologia Market integration services market and providers for users required by various SierraTecnologia packages. Validator functionality, and basic controller included out-of-the-box.
📚 Índice
- Introdução
- Instalação
- Arquitetura e Estrutura Interna
- Principais Funcionalidades
- Uso Prático
- Integração com o Ecossistema SierraTecnologia
- Extensão e Customização
- Exemplos Reais
- Guia de Contribuição
- Testes e Qualidade
- Changelog
- Suporte
🚀 Introdução
O que é o Market?
Market é uma solução modular completa de e-commerce e marketplace desenvolvida pela SierraTecnologia / Rica Soluções, projetada para integração nativa com aplicações Laravel. O pacote oferece uma camada robusta e escalável para gerenciamento de produtos, carrinho de compras, processamento de pagamentos, gestão de pedidos e assinaturas recorrentes.
Objetivo e Contexto de Uso
O Market integra o ecossistema SierraTecnologia, servindo como módulo central para operações comerciais em aplicações corporativas e startups que necessitam de:
- Catálogo de produtos com variantes e gestão de estoque
- Carrinho de compras persistente e seguro
- Checkout completo com múltiplos métodos de pagamento
- Gestão de pedidos e transações financeiras
- Assinaturas e planos recorrentes
- Sistema de cupons e descontos
- Analytics e relatórios comerciais
Principais Benefícios e Diferenciais
✅ Modularidade: Arquitetura desacoplada seguindo princípios SOLID ✅ Escalabilidade: Suporte a múltiplos marketplaces e multi-tenancy ✅ Integração Nativa: Comunicação fluida com Payment-Laravel, Pedreiro, Media-Manager ✅ Flexibilidade: Sistema de variantes dinâmicas com modificadores de preço/peso ✅ Segurança: Criptografia de IDs sensíveis, validação robusta, proteção CSRF ✅ Analytics Avançado: Dashboard com métricas de vendas, refundos e assinaturas ✅ Multi-canal: APIs REST para integração com mobile e SPAs
Relação com o Ecossistema Rica Soluções
O Market se comunica com outros pacotes da SierraTecnologia através de contratos e interfaces bem definidas:
Market (Commerce Core)
├── Payment-Laravel (Gateway de Pagamento)
├── Pedreiro (Admin Scaffolding)
├── Media-Manager (Gestão de Imagens/Arquivos)
├── Crypto (Criptografia e UUID)
├── Bancario (Integrações Bancárias)
├── Muleta (Utilitários Base)
└── Locaravel (Localização e URLs)
💿 Instalação
Requisitos Mínimos
- PHP: ^7.2 | ^8.0 | ^8.1 | ^8.2
- Laravel: ^7.0 | ^8.0 | ^9.0 | ^10.0
- Extensões PHP:
mbstring,openssl,pdo,tokenizer,json,curl - Banco de Dados: MySQL 5.7+ / PostgreSQL 9.6+ / MariaDB 10.2+
Instalação via Composer
composer require sierratecnologia/market
Publicação de Configurações e Assets
# Publicar arquivo de configuração php artisan vendor:publish --tag=sitec-config # Publicar views (opcional, para customização) php artisan vendor:publish --tag=sitec-views # Publicar traduções php artisan vendor:publish --tag=sitec-lang # Publicar assets públicos (CSS/JS) php artisan vendor:publish --tag=sitec-public
Executar Migrações
php artisan migrate
Isso criará as tabelas:
products- Catálogo de produtosproduct_variants- Variantes (tamanho, cor, etc.)cart- Carrinho de comprasorders- Pedidosorder_items- Itens dos pedidostransactions- Transações financeirasrefunds- Reembolsosplans- Planos de assinaturacoupons- Cupons de descontofavorites- Lista de desejos
Registro de Service Providers e Aliases
Registro Automático (Laravel 5.5+)
O MarketProvider é registrado automaticamente via Package Discovery.
Registro Manual (Laravel 5.4 ou inferior)
Adicione ao config/app.php:
'providers' => [ // ... Market\MarketProvider::class, ], 'aliases' => [ // ... 'Market' => Market\Facades\Market::class, 'StoreHelper' => Market\Facades\StoreHelper::class, ],
Configuração Inicial
Edite config/sitec/market.php:
return [ // Habilitar suporte a múltiplos marketplaces 'multi-markets' => true, // Habilitar sistema de planos/assinaturas 'have-plans' => true, // Habilitar sistema de cupons 'have-coupons' => true, // Prefixo de URL da loja 'store_url_prefix' => 'commerce', // Moeda padrão (ISO 4217) 'currency' => 'BRL', // Incluir frete no cálculo de impostos 'taxes_include_shipping' => true, ];
Configure suas credenciais de pagamento no .env:
SITECPAYMENT_SECRET=sk_test_xxxxxxxxxxxxx SITECPAYMENT_PUBLIC=pk_test_xxxxxxxxxxxxx
🏗️ Arquitetura e Estrutura Interna
Organização dos Diretórios e Namespaces
src/
├── Cacheable/ # Utilitários de cache para queries Eloquent
├── Console/ # Comandos Artisan e Kernel customizado
├── Contracts/ # Contratos abstratos e interfaces
├── Exceptions/ # Exceções customizadas do domínio
├── Facades/ # Facades (Market, StoreHelper)
├── Http/
│ ├── Controllers/ # Controladores MVC
│ │ ├── Admin/ # Painel administrativo (CRUD)
│ │ ├── Api/ # Endpoints REST (cart, favorites)
│ │ └── Master/ # Dashboard de analytics
│ ├── Policies/ # Políticas de autorização
│ └── Requests/ # Form Requests (validação)
├── Interfaces/ # Contratos de serviços e repositórios
├── Models/ # Modelos Eloquent (14 models)
├── Observers/ # Observadores de eventos de modelo
├── Repositories/ # Camada de acesso a dados (10 repos)
├── Resources/ # API Resources (serialização JSON)
├── Scopes/ # Query Scopes globais/locais
├── Services/ # Lógica de negócio (19 services)
├── Traits/ # Funcionalidades reutilizáveis
├── Market.php # Classe principal do pacote
└── MarketProvider.php # Service Provider Laravel
Padrões Arquiteturais
O Market implementa uma arquitetura em camadas inspirada em Domain-Driven Design (DDD) e Clean Architecture:
1. Camada de Domínio (Domain Layer)
Contém as regras de negócio puras e entidades do domínio:
// Models (Entidades) Market\Models\Product # Produtos do catálogo Market\Models\Order # Pedidos (Aggregate Root) Market\Models\OrderItem # Itens do pedido Market\Models\Transaction # Transações financeiras Market\Models\Cart # Carrinho de compras Market\Models\Variant # Variantes de produtos // Value Objects Market\Models\Currency # Objeto de valor monetário
Exemplo de Aggregate Root (Order):
namespace Market\Models; class Order extends MarketModel { // Aggregate que coordena OrderItems e Transaction public function items() { return $this->hasMany(OrderItem::class); } public function transaction() { return $this->belongsTo(Transaction::class); } // Regra de negócio: cancelamento cascata public function cancel() { foreach ($this->items as $item) { $item->refund(); } $this->transaction->refund(); $this->update(['status' => 'cancelled']); } }
2. Camada de Aplicação (Application Layer)
Orquestra casos de uso através de Services:
// Serviços (Casos de Uso) Market\Services\CartService # Gerenciamento do carrinho Market\Services\PaymentService # Processamento de pagamentos Market\Services\OrderService # Gestão de pedidos Market\Services\ProductService # CRUD de produtos Market\Services\LogisticService # Cálculo de frete e impostos Market\Services\AnalyticsService # Métricas e relatórios
Exemplo de Service (PaymentService):
namespace Market\Services; class PaymentService { protected $transactionService; protected $orderService; protected $logisticService; public function __construct( TransactionService $transactionService, OrderService $orderService, LogisticService $logisticService ) { $this->transactionService = $transactionService; $this->orderService = $orderService; $this->logisticService = $logisticService; } public function purchase($user, $cardToken, $cart) { DB::beginTransaction(); try { // 1. Processar pagamento via gateway $charge = $user->meta->charge( $cart->total(), $cardToken ); // 2. Registrar transação $transaction = $this->transactionService->create([ 'user_id' => $user->id, 'provider' => 'sitecpayment', 'provider_id' => $charge->id, 'amount' => $cart->total(), ]); // 3. Criar pedido $order = $this->createOrder($user, $transaction, $cart); // 4. Processar logística $this->logisticService->afterPurchase($order); // 5. Limpar carrinho $cart->empty(); DB::commit(); return $order; } catch (\Exception $e) { DB::rollBack(); throw new PaymentException($e->getMessage()); } } }
3. Camada de Infraestrutura (Infrastructure Layer)
Implementa persistência e integrações externas:
// Repositórios (Data Access) Market\Repositories\ProductRepository Market\Repositories\OrderRepository Market\Repositories\CartRepository Market\Repositories\TransactionRepository // Service Provider (Dependency Injection) Market\MarketProvider // Migrations (Schema Management) database/migrations/
Exemplo de Repository Pattern:
namespace Market\Repositories; class ProductRepository { protected $model; public function __construct(Product $model) { $this->model = $model; } public function paginated($perPage = 25) { return $this->model ->where('is_published', true) ->where('is_available', true) ->orderBy('created_at', 'desc') ->paginate($perPage); } public function findByURL($url) { return $this->model ->where('url', $url) ->firstOrFail(); } }
Convenções da SierraTecnologia para Modularidade e Escalabilidade
- Injeção de Dependência: Todos os services usam constructor injection
- Interface Segregation: Contratos específicos em
Interfaces/ - Single Responsibility: Cada service tem uma responsabilidade única
- Repository Pattern: Abstração de acesso a dados
- Facades Opcionais: Acesso via DI ou Facades conforme preferência
- Event Observers: Callbacks de modelo centralizados
- Configuração Centralizada:
config/sitec/market.php - Logging Dedicado: Canal
sitec-marketseparado
🎯 Principais Funcionalidades
1. Gestão de Produtos
Estrutura do Modelo Product
namespace Market\Models; class Product extends MarketModel { protected $fillable = [ 'name', // Nome do produto 'url', // Slug URL-friendly 'code', // SKU/Código interno 'price', // Preço em centavos (int) 'weight', // Peso em gramas (int) 'width', // Largura em cm 'height', // Altura em cm 'depth', // Profundidade em cm 'discount', // Desconto em centavos 'stock', // Quantidade em estoque 'is_published', // Publicado? 'is_available', // Disponível? 'is_featured', // Produto destaque? 'hero_image', // Imagem principal (path) 'file', // Arquivo digital (downloads) 'details', // JSON: descrição, SEO, etc. ]; // Accessors para conversão automática public function getPriceAttribute($value) { return $value / 100; // centavos → reais } public function setPriceAttribute($value) { $this->attributes['price'] = $value * 100; // reais → centavos } // Relacionamentos public function variants() { return $this->hasMany(Variant::class); } public function images() { return $this->hasMany(Image::class, 'entity_id') ->where('entity_type', self::class); } }
Criando Produtos via Service
use Market\Services\ProductService; $productService = app(ProductService::class); $product = $productService->create([ 'name' => 'Notebook Dell XPS 15', 'url' => 'notebook-dell-xps-15', 'code' => 'DELL-XPS15-2024', 'price' => 8999.90, // Será armazenado como 899990 centavos 'weight' => 1800, // 1.8kg em gramas 'stock' => 50, 'is_published' => true, 'is_available' => true, 'details' => [ 'description' => 'Notebook de alta performance...', 'specs' => [ 'processor' => 'Intel Core i7', 'ram' => '16GB DDR4', 'storage' => 'SSD 512GB NVMe' ], 'seo' => [ 'meta_description' => 'Compre o melhor notebook...', 'keywords' => 'notebook, dell, xps' ] ] ]);
2. Sistema de Variantes Avançado
O Market suporta variantes com modificadores de preço e peso:
// Criando variantes $variant1 = $product->variants()->create([ 'key' => 'cor', 'value' => 'Prata(+$0)[+0g]' // Sem modificadores ]); $variant2 = $product->variants()->create([ 'key' => 'cor', 'value' => 'Dourado(+$299.90)[+50g]' // +R$299,90 e +50g ]); $variant3 = $product->variants()->create([ 'key' => 'memoria', 'value' => '32GB(+$899.00)[+0g]' // Upgrade de RAM ]);
Sintaxe de Modificadores:
(+$valor)ou(-$valor): Ajuste de preço[+peso]ou[-peso]: Ajuste de peso em gramas- Múltiplas variantes:
"Cor|Tamanho|Material"
Cálculo Automático no Carrinho:
// Adicionar ao carrinho com variantes $cart->add([ 'product_id' => $product->id, 'quantity' => 1, 'variants' => 'Dourado|32GB', // +R$1.198,90 ]); // Preço calculado: // Base: R$8.999,90 // + Cor Dourado: R$299,90 // + 32GB RAM: R$899,00 // = R$10.198,80
3. Carrinho de Compras
Dual Storage: Sessão (Guest) + Database (User)
use Market\Services\CartService; $cartService = app(CartService::class); // Adicionar item ao carrinho $cartService->addToCart([ 'product_id' => 1, 'quantity' => 2, 'variants' => 'Vermelho|Grande', ]); // Obter conteúdo do carrinho $items = $cartService->contents(); // Totais $subtotal = $cartService->getCartSubTotal(); // Soma dos produtos $tax = $cartService->getCartTax(); // Impostos $shipping = $cartService->getCartShipping(); // Frete $total = $cartService->getCartTotal(); // Total final // Aplicar cupom $cartService->addCoupon('DESCONTO10'); // Remover item $cartService->removeFromCart($itemId); // Esvaziar carrinho $cartService->emptyCart();
Sincronização Automática (Guest → User)
Quando um usuário não autenticado faz login, o carrinho da sessão é automaticamente mesclado com o carrinho do banco de dados:
// Em CartRepository@syncronize() public function syncronize($userId) { $sessionCart = session()->get('cart', []); foreach ($sessionCart as $item) { $this->model->create([ 'user_id' => $userId, 'product_id' => $item['product_id'], 'quantity' => $item['quantity'], 'variants' => $item['variants'], ]); } session()->forget('cart'); }
4. Checkout e Processamento de Pagamentos
Fluxo Completo de Checkout
// 1. Página de Confirmação (/checkout) // Usuário revisa itens, endereço, frete // 2. Página de Pagamento (/payment) // Usuário insere dados do cartão // 3. Processar Pagamento (POST /process) use Market\Services\PaymentService; $paymentService = app(PaymentService::class); $order = $paymentService->purchase( auth()->user(), $request->input('card_token'), // Token do gateway $cartService->getCart() ); // 4. Página de Sucesso (/complete) // Exibir número do pedido e detalhes
Integração com Payment-Laravel (SierraTecnologia Gateway)
// O usuário precisa ter um customer_id no gateway if (!auth()->user()->meta->hasCustomer()) { auth()->user()->meta->createAsSierraTecnologiaCustomer( $request->input('card_token') ); } // Cobrar do cartão $charge = auth()->user()->meta->charge( $cart->total(), $request->input('card_token') ); // Cobrar do último cartão salvo $charge = auth()->user()->meta->chargeWithLastCard($amount);
5. Gestão de Pedidos e Transações
Estrutura de Pedido (Order)
namespace Market\Models; class Order extends MarketModel { protected $fillable = [ 'uuid', // UUID único do pedido 'user_id', // Cliente 'transaction_id', // Transação associada 'shipping_address', // JSON: endereço de entrega 'billing_address', // JSON: endereço de cobrança 'is_shipped', // Enviado? 'tracking_number', // Código de rastreio 'status', // pending|complete|cancelled 'notes', // Observações 'details', // JSON: metadados adicionais ]; protected $casts = [ 'shipping_address' => 'array', 'billing_address' => 'array', 'details' => 'array', ]; }
Criando e Gerenciando Pedidos
use Market\Services\OrderService; $orderService = app(OrderService::class); // Criar pedido $order = $orderService->create([ 'user_id' => $user->id, 'transaction_id' => $transaction->id, 'shipping_address' => [ 'street' => 'Rua das Flores, 123', 'city' => 'Rio de Janeiro', 'state' => 'RJ', 'zipcode' => '20000-000', ], 'items' => [ ['product_id' => 1, 'quantity' => 2, 'variants' => 'Azul|M'], ['product_id' => 5, 'quantity' => 1, 'variants' => null], ], ]); // Buscar pedidos do cliente $orders = $orderService->getByCustomer($user->id); // Cancelar pedido (refund automático) $orderService->cancel($order->id); // Atualizar status de envio $orderService->update($order->id, [ 'is_shipped' => true, 'tracking_number' => 'BR123456789XY', ]);
6. Sistema de Assinaturas (Plans)
Criando Planos
use Market\Services\PlanService; $planService = app(PlanService::class); $plan = $planService->create([ 'name' => 'Premium Mensal', 'amount' => 49.90, // R$49,90/mês 'interval' => 'month', // week|month|year 'currency' => 'BRL', 'trial_days' => 7, // 7 dias grátis 'is_featured' => true, 'enabled' => true, 'descriptors' => [ 'features' => [ 'Acesso ilimitado', 'Suporte prioritário', 'Downloads sem limite' ] ] ]);
Assinando um Plano
use Market\Services\SubscriptionService; $subscriptionService = app(SubscriptionService::class); // Criar assinatura $subscription = auth()->user()->meta->newSubscription( 'Premium Mensal', $plan->sitecpayment_id )->create($cardToken); // Cancelar assinatura auth()->user()->meta->subscription('Premium Mensal')->cancel(); // Verificar se está assinado if (auth()->user()->meta->subscribed('Premium Mensal')) { // Usuário tem acesso premium }
7. Cupons e Descontos
use Market\Services\CouponService; $couponService = app(CouponService::class); // Criar cupom de 10% de desconto $coupon = $couponService->create([ 'code' => 'DESCONTO10', 'discount_type' => 'percentage', // ou 'dollar' 'amount' => 10, // 10% 'limit' => 100, // Máximo 100 usos 'start_date' => now(), 'end_date' => now()->addDays(30), 'for_subscriptions' => false, ]); // Criar cupom de R$50 off $coupon = $couponService->create([ 'code' => '50REAIS', 'discount_type' => 'dollar', 'amount' => 50.00, 'limit' => 50, ]); // Aplicar cupom no checkout $cartService->addCoupon('DESCONTO10');
8. Analytics e Relatórios
use Market\Services\AnalyticsService; $analyticsService = app(AnalyticsService::class); // Obter transações dos últimos 30 dias $transactions = $analyticsService->getTransactionsByDays(30); // Calcular balanço (receita - reembolsos) $balance = $analyticsService->balanceValues($transactions); // Receita mensal $monthlyRevenue = $analyticsService->overMonths(12); // Exibir no dashboard return view('market::master.analytics', [ 'revenue' => $balance['income'], 'refunds' => $balance['refunds'], 'profit' => $balance['income'] - $balance['refunds'], 'chart_data' => $monthlyRevenue, ]);
🔧 Uso Prático
Integração em Aplicação Laravel Existente
1. Adicionar Rotas Personalizadas
// routes/web.php use Market\Http\Controllers\ProductController; use Market\Http\Controllers\CartController; use Market\Http\Controllers\CheckoutController; // Vitrine pública Route::get('/loja', [ProductController::class, 'index']); Route::get('/loja/produto/{url}', [ProductController::class, 'show']); // Carrinho Route::middleware('auth')->group(function () { Route::get('/carrinho', [CartController::class, 'index']); Route::post('/carrinho/adicionar', [CartController::class, 'add']); // Checkout Route::get('/finalizar', [CheckoutController::class, 'confirm']); Route::post('/processar-pagamento', [CheckoutController::class, 'process']); });
2. Customizar Views
// Publicar views php artisan vendor:publish --tag=sitec-views // Customizar: resources/views/vendor/market/products/show.blade.php @extends('layouts.app') @section('content') <div class="product-detail"> <h1>{{ $product->name }}</h1> <p class="price">R$ {{ number_format($product->price, 2, ',', '.') }}</p> @if($product->variants->count()) <div class="variants"> @foreach($product->variants as $variant) <label> <input type="radio" name="variant" value="{{ $variant->value }}"> {{ $variant->value }} </label> @endforeach </div> @endif <button onclick="addToCart({{ $product->id }})"> Adicionar ao Carrinho </button> </div> @endsection
3. Criar Middleware Personalizado
// app/Http/Middleware/CheckProductAvailability.php namespace App\Http\Middleware; use Closure; use Market\Models\Product; class CheckProductAvailability { public function handle($request, Closure $next) { $product = Product::find($request->route('id')); if (!$product || !$product->is_available) { return redirect('/loja')->with('error', 'Produto indisponível'); } return $next($request); } }
Exemplo: Integração com Gateway de Pagamento
// app/Services/CustomPaymentService.php namespace App\Services; use Market\Services\PaymentService as BasePaymentService; use Market\Services\OrderService; use Market\Services\TransactionService; class CustomPaymentService extends BasePaymentService { public function processWithPix($user, $cart) { // 1. Gerar QR Code PIX $pixData = $this->pixGateway->generateQRCode([ 'amount' => $cart->total(), 'description' => 'Pedido #' . uniqid(), ]); // 2. Criar transação pendente $transaction = $this->transactionService->create([ 'user_id' => $user->id, 'provider' => 'pix', 'provider_id' => $pixData['id'], 'state' => 'pending', 'amount' => $cart->total(), ]); // 3. Criar pedido aguardando pagamento $order = $this->createOrder($user, $transaction, $cart); return [ 'order' => $order, 'pix_qrcode' => $pixData['qrcode'], 'pix_string' => $pixData['emv'], ]; } }
Exemplo: Webhook para Confirmação de Pagamento
// routes/api.php Route::post('/webhook/payment-confirmation', [WebhookController::class, 'handle']); // app/Http/Controllers/WebhookController.php namespace App\Http\Controllers; use Market\Services\OrderService; use Market\Services\TransactionService; use Market\Services\LogisticService; class WebhookController extends Controller { public function handle(Request $request) { $signature = $request->header('X-Webhook-Signature'); // Validar assinatura if (!$this->validateSignature($signature, $request->getContent())) { return response()->json(['error' => 'Invalid signature'], 401); } $data = $request->json()->all(); if ($data['event'] === 'payment.approved') { $transaction = app(TransactionService::class) ->findByProviderId($data['payment_id']); // Atualizar transação $transaction->update(['state' => 'approved']); // Atualizar pedido $order = $transaction->order; $order->update(['status' => 'complete']); // Processar logística app(LogisticService::class)->afterPurchase($order); return response()->json(['status' => 'processed']); } return response()->json(['status' => 'ignored']); } }
🔗 Integração com o Ecossistema SierraTecnologia
Comunicação entre Pacotes
1. Payment-Laravel (Gateway de Pagamento)
// O Market depende do Payment-Laravel para processar pagamentos // Criar customer no gateway $user->meta->createAsSierraTecnologiaCustomer($cardToken); // Cobrar valor $charge = $user->meta->charge($amount, $cardToken); // Cobrar com último cartão salvo $charge = $user->meta->chargeWithLastCard($amount); // Reembolsar $refund = $user->meta->refund($chargeId, $amount); // Criar assinatura $subscription = $user->meta->newSubscription('plan-name', $planId) ->trialDays(7) ->create($cardToken);
2. Media-Manager (Gestão de Imagens)
use SierraTecnologia\MediaManager\Models\Image; // Associar imagens a produtos $product->images()->create([ 'path' => '/storage/products/notebook-1.jpg', 'alt' => 'Notebook Dell XPS 15', 'title' => 'Imagem principal', ]); // Recuperar imagens $images = $product->images; // Hero image (imagem principal) $product->update([ 'hero_image' => '/storage/products/hero.jpg' ]);
3. Pedreiro (Admin Scaffolding)
O Market registra automaticamente itens de menu no painel admin:
// Em MarketProvider@boot() $menuItens = [ 'Commerce' => [ 'Produtos' => [ 'icon' => 'pe-7s-cart', 'route' => 'admin.market.products.index', ], 'Pedidos' => [ 'icon' => 'pe-7s-note2', 'route' => 'master.market.orders.index', ], 'Transações' => [ 'icon' => 'pe-7s-cash', 'route' => 'master.market.transactions.index', ], ], ]; event(new \Pedreiro\Events\MenuRegistered($menuItens));
4. Crypto (Criptografia e UUID)
use function SierraTecnologia\Crypto\crypto_encrypt; use function SierraTecnologia\Crypto\crypto_decrypt; // Gerar UUID para transações $transaction->uuid = \Ramsey\Uuid\Uuid::uuid4()->toString(); // Criptografar IDs sensíveis em URLs $encryptedId = crypto_encrypt($order->id); $url = route('order.show', $encryptedId); // Descriptografar $orderId = crypto_decrypt($request->route('id'));
5. Locaravel (Localização)
use function SierraTecnologia\Locaravel\RiCaService; // Converter nome de produto para URL slug $product->url = RiCaService::convertToURL($product->name); // "Notebook Dell XPS 15" → "notebook-dell-xps-15"
Padrões de Versionamento, Testes e CI/CD
Versionamento Semântico
O Market segue Semantic Versioning 2.0:
- MAJOR (0.x.x → 1.0.0): Breaking changes
- MINOR (0.4.x → 0.5.0): Novas funcionalidades (backward-compatible)
- PATCH (0.4.4 → 0.4.5): Bug fixes
Estratégia de Branches (Git Flow)
main (production)
└── develop (integration)
├── feature/cart-improvements
├── feature/pix-integration
└── bugfix/checkout-validation
Aplicação em Ambientes de Microserviços
O Market pode ser usado em arquitetura de microserviços:
┌─────────────────────────────────────────┐
│ API Gateway (Laravel + Market) │
│ - Endpoints REST │
│ - Autenticação JWT │
└─────────────────┬───────────────────────┘
│
┌───────────┴───────────┐
│ │
┌─────▼──────┐ ┌────────▼────────┐
│ Product │ │ Order Service │
│ Service │ │ (Market Core) │
│ (Market) │ └─────────────────┘
└────────────┘
Exemplo de API REST:
// routes/api.php Route::prefix('v1')->middleware('auth:sanctum')->group(function () { // Produtos Route::get('/products', [Api\ProductController::class, 'index']); Route::get('/products/{id}', [Api\ProductController::class, 'show']); // Carrinho Route::get('/cart', [Api\CartController::class, 'index']); Route::post('/cart', [Api\CartController::class, 'add']); Route::delete('/cart/{id}', [Api\CartController::class, 'remove']); // Pedidos Route::get('/orders', [Api\OrderController::class, 'index']); Route::get('/orders/{uuid}', [Api\OrderController::class, 'show']); Route::post('/orders', [Api\OrderController::class, 'create']); });
🎨 Extensão e Customização
Criar Novos Módulos (Ex: Promoções)
1. Criar Model
// app/Models/Promotion.php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Market\Models\Product; class Promotion extends Model { protected $fillable = [ 'name', 'discount_percentage', 'start_date', 'end_date', 'active', ]; protected $casts = [ 'start_date' => 'datetime', 'end_date' => 'datetime', ]; public function products() { return $this->belongsToMany(Product::class); } public function isActive() { return $this->active && now()->between($this->start_date, $this->end_date); } }
2. Criar Migration
// database/migrations/2024_xx_xx_create_promotions_table.php public function up() { Schema::create('promotions', function (Blueprint $table) { $table->id(); $table->string('name'); $table->integer('discount_percentage'); $table->timestamp('start_date'); $table->timestamp('end_date'); $table->boolean('active')->default(true); $table->timestamps(); }); Schema::create('product_promotion', function (Blueprint $table) { $table->foreignId('product_id')->constrained()->onDelete('cascade'); $table->foreignId('promotion_id')->constrained()->onDelete('cascade'); $table->primary(['product_id', 'promotion_id']); }); }
3. Estender ProductService
// app/Services/PromotionService.php namespace App\Services; use Market\Services\ProductService; use App\Models\Promotion; class PromotionService { protected $productService; public function __construct(ProductService $productService) { $this->productService = $productService; } public function applyPromotion(Promotion $promotion, $products) { foreach ($products as $product) { $promotion->products()->attach($product->id); } } public function getPromotionalPrice($product) { $promotion = $product->promotions() ->where('active', true) ->where('start_date', '<=', now()) ->where('end_date', '>=', now()) ->first(); if ($promotion) { return $product->price * (1 - $promotion->discount_percentage / 100); } return $product->price; } }
Substituir Classes Padrão via Injeção de Dependência
// app/Providers/AppServiceProvider.php use Market\Services\PaymentService; use App\Services\CustomPaymentService; public function register() { // Substituir PaymentService por implementação customizada $this->app->bind(PaymentService::class, CustomPaymentService::class); }
Boas Práticas para Evitar Breaking Changes
- Nunca modifique arquivos do vendor/: Use inheritance ou DI
- Publique e customize views:
vendor:publish --tag=sitec-views - Use eventos e listeners: Para adicionar lógica sem alterar código core
- Crie observers customizados: Para estender comportamento de models
// app/Observers/ProductObserver.php namespace App\Observers; use Market\Models\Product; class ProductObserver { public function created(Product $product) { // Enviar email para admin \Mail::to('admin@loja.com')->send(new ProductCreatedMail($product)); // Invalidar cache \Cache::forget('featured-products'); } } // Registrar em AppServiceProvider use Market\Models\Product; use App\Observers\ProductObserver; public function boot() { Product::observe(ProductObserver::class); }
💼 Exemplos Reais
Caso de Uso: Marketplace Multi-Vendor
// 1. Adicionar campo vendor_id aos produtos Schema::table('products', function (Blueprint $table) { $table->foreignId('vendor_id')->nullable()->constrained('users'); }); // 2. Criar filtro por vendor $vendorProducts = app(ProductService::class)->paginated([ 'vendor_id' => $vendorId ]); // 3. Comissão automática no checkout public function afterPurchase($order) { foreach ($order->items as $item) { $product = $item->product; $vendor = $product->vendor; $commission = $item->total * 0.85; // 85% para o vendor VendorPayout::create([ 'vendor_id' => $vendor->id, 'order_item_id' => $item->id, 'amount' => $commission, ]); } }
Caso de Uso: Produtos Digitais (Downloads)
// 1. Criar rota de download protegida Route::get('/download/{order}/{item}', [DownloadController::class, 'download']) ->middleware('auth'); // 2. Controller de download public function download(Order $order, OrderItem $item) { // Verificar se o pedido pertence ao usuário if ($order->user_id !== auth()->id()) { abort(403); } // Verificar se o item tem arquivo digital if (!$item->product->file) { abort(404, 'Arquivo não encontrado'); } // Registrar download DownloadLog::create([ 'user_id' => auth()->id(), 'product_id' => $item->product_id, 'ip' => request()->ip(), ]); // Forçar download return Storage::download($item->product->file); }
Caso de Uso: Assinatura com Conteúdo Exclusivo
// Middleware para verificar assinatura public function handle($request, Closure $next) { if (!auth()->user()->meta->subscribed('Premium')) { return redirect('/planos')->with('error', 'Assine o plano Premium para acessar'); } return $next($request); } // Usar em rotas Route::middleware(['auth', 'subscription:Premium'])->group(function () { Route::get('/cursos-exclusivos', [CourseController::class, 'index']); });
Demonstração: Antes e Depois
ANTES (sem Market):
// Código espaguete misturado no controller public function checkout(Request $request) { $cart = Session::get('cart'); $total = 0; foreach ($cart as $item) { $total += $item['price'] * $item['qty']; } $charge = \Stripe\Charge::create([ 'amount' => $total * 100, 'currency' => 'brl', 'source' => $request->token, ]); DB::table('orders')->insert([ 'user_id' => auth()->id(), 'total' => $total, 'created_at' => now(), ]); Session::forget('cart'); return redirect('/success'); }
DEPOIS (com Market):
// Código limpo, testável e reutilizável public function checkout(Request $request) { $order = app(PaymentService::class)->purchase( auth()->user(), $request->input('card_token'), app(CartService::class)->getCart() ); return redirect()->route('order.complete', $order->uuid); }
Benefícios:
- ✅ 90% menos código
- ✅ Transações atômicas (rollback automático)
- ✅ Validação centralizada
- ✅ Logs automáticos
- ✅ Facilidade de teste unitário
- ✅ Reutilizável em múltiplos projetos
🧪 Testes e Qualidade
Executar Testes Localmente
# Testes unitários e de integração composer test # ou vendor/bin/phpunit # Testes com cobertura composer test-coverage
Análise Estática
# PHPStan (nível 8) vendor/bin/phpstan analyse src/ # Psalm composer psalm # ou vendor/bin/psalm
Verificação de Código (Code Style)
# PHPCS (PSR-12) vendor/bin/phpcs --standard=PSR12 src/ # PHP CS Fixer (correção automática) composer format # ou vendor/bin/php-cs-fixer fix --allow-risky=yes
PHPMD (Mess Detector)
vendor/bin/phpmd src/ text cleancode,codesize,controversial,design,naming,unusedcode
🤝 Guia de Contribuição
Como Contribuir
- Fork o repositório
- Crie uma branch para sua feature (
git checkout -b feature/nova-funcionalidade) - Commit suas mudanças (
git commit -m 'feat: adiciona nova funcionalidade') - Push para a branch (
git push origin feature/nova-funcionalidade) - Abra um Pull Request
Padrões de Commits
Seguimos o Conventional Commits:
feat: adiciona suporte a pagamento via PIX
fix: corrige cálculo de frete para produtos pesados
docs: atualiza README com exemplos de uso
style: formata código conforme PSR-12
refactor: reorganiza services em subdiretórios
test: adiciona testes para ProductService
chore: atualiza dependências do composer
Padrões de Branches
main: Branch de produção (somente merges via PR)develop: Branch de desenvolvimento (integração)feature/nome-da-feature: Novas funcionalidadesbugfix/nome-do-bug: Correções de bugshotfix/nome-do-hotfix: Correções urgentes em produção
Política de Licença e Contato
- Licença: MIT (veja LICENSE)
- Email: help@sierratecnologia.com.br
- Chat: Slack da SierraTecnologia
- Twitter: @sierratecnologia
📝 Changelog
Consulte o CHANGELOG.md para histórico completo de versões.
💬 Suporte
Os seguintes canais de suporte estão disponíveis:
🔐 Vulnerabilidades de Segurança
Se você descobrir uma vulnerabilidade de segurança neste projeto, envie um e-mail para help@sierratecnologia.com.br. Todas as vulnerabilidades serão prontamente tratadas.
About SierraTecnologia
SierraTecnologia is a software solutions startup, specialized in integrated enterprise solutions for SMEs established in Rio de Janeiro, Brazil since June 2008. We believe that our drive The Value, The Reach, and The Impact is what differentiates us and unleash the endless possibilities of our philosophy through the power of software. We like to call it Innovation At The Speed Of Life. That’s how we do our share of advancing humanity.
License
This software is released under The MIT License (MIT).
(c) 2008-2020 SierraTecnologia, Some rights reserved.