feat: split 'reject' price type into 'reject_capital' and 'reject_selling', update related components and database migration
This commit is contained in:
parent
0947cf3737
commit
0998c81803
@ -300,7 +300,7 @@ ## Enums
|
||||
| `PayrollPeriodStatus` | open, closed | payroll_periods.status |
|
||||
| `PayrollStatus` | unpaid, paid, cancelled | payrolls.status |
|
||||
| `Permission` | — | Permission action names |
|
||||
| `PriceType` | retail, wholesale, capital | product_prices.type, orders.price_type |
|
||||
| `PriceType` | retail, wholesale, capital, reject_capital, reject_selling | product_prices.type, orders.price_type |
|
||||
| `ProductStatus` | active, draft, inactive, pending, rejected | products.status |
|
||||
| `ProductStockQuality` | good, reject | order_items.stock_quality, restocks.stock_type, stok_opname_items.stock_quality |
|
||||
| `RawMaterialUnit` | kg, meter, yard | raw_materials.unit |
|
||||
|
||||
@ -108,7 +108,7 @@ public function fix(): array
|
||||
private function resolvePriceType(string $orderPriceType, string $stockQuality): string
|
||||
{
|
||||
if ($stockQuality === ProductStockQuality::REJECT->value) {
|
||||
return PriceType::REJECT->value;
|
||||
return PriceType::REJECT_SELLING->value;
|
||||
}
|
||||
|
||||
$map = [
|
||||
|
||||
@ -16,7 +16,8 @@ enum PriceType: string
|
||||
case TIKTOK = 'tiktok';
|
||||
case SHOPEE = 'shopee';
|
||||
case CAPITAL = 'capital';
|
||||
case REJECT = 'reject';
|
||||
case REJECT_CAPITAL = 'reject_capital';
|
||||
case REJECT_SELLING = 'reject_selling';
|
||||
|
||||
public function label(): string
|
||||
{
|
||||
@ -29,7 +30,8 @@ public function label(): string
|
||||
self::TIKTOK => 'TikTok',
|
||||
self::SHOPEE => 'Shopee',
|
||||
self::CAPITAL => 'Modal',
|
||||
self::REJECT => 'Reject',
|
||||
self::REJECT_CAPITAL => 'Reject Modal',
|
||||
self::REJECT_SELLING => 'Reject Jual',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ public function rules(): array
|
||||
return [
|
||||
'stock_type' => ['sometimes', 'required', Rule::in(ProductStockQuality::values())],
|
||||
'channel' => ['sometimes', 'required', Rule::in(OrderChannel::values())],
|
||||
'price_type' => ['sometimes', 'required', Rule::in(array_diff(PriceType::values(), [PriceType::CAPITAL->value]))],
|
||||
'price_type' => ['sometimes', 'required', Rule::in(array_diff(PriceType::values(), [PriceType::CAPITAL->value, PriceType::REJECT_CAPITAL->value]))],
|
||||
'payment_type' => ['sometimes', 'required', Rule::in(PaymentType::values())],
|
||||
'customer_id' => ['nullable', 'integer', Rule::exists('customers', 'id')],
|
||||
'marketing_id' => ['nullable', 'integer', Rule::exists('users', 'id')],
|
||||
|
||||
@ -188,7 +188,7 @@ public function destroy(Restock $restock): bool
|
||||
private function buildItemRows(array $items, string $stockType, $now, int &$total): array
|
||||
{
|
||||
$priceType = $stockType === ProductStockQuality::REJECT->value
|
||||
? PriceType::REJECT
|
||||
? PriceType::REJECT_CAPITAL
|
||||
: PriceType::CAPITAL;
|
||||
|
||||
$variantIds = collect($items)->pluck('product_variant_id')->unique()->all();
|
||||
|
||||
@ -33,6 +33,7 @@ class TransactionService
|
||||
PriceType::RETAIL->value => PriceType::RETAIL,
|
||||
PriceType::TIKTOK->value => PriceType::TIKTOK,
|
||||
PriceType::SHOPEE->value => PriceType::SHOPEE,
|
||||
PriceType::REJECT_SELLING->value => PriceType::REJECT_SELLING,
|
||||
];
|
||||
|
||||
public function __construct(
|
||||
@ -355,7 +356,7 @@ public function updateStatus(Order $order, string $status): Order
|
||||
private function buildItemRows(array $items, string $stockType, string $priceType, $now, int &$subtotal, int &$totalCost): array
|
||||
{
|
||||
$resolvedPriceType = $stockType === ProductStockQuality::REJECT->value
|
||||
? PriceType::REJECT
|
||||
? PriceType::REJECT_SELLING
|
||||
: (self::SELLING_PRICE_MAP[$priceType] ?? PriceType::RETAIL);
|
||||
|
||||
$variantIds = collect($items)->pluck('product_variant_id')->unique()->all();
|
||||
@ -375,9 +376,13 @@ private function buildItemRows(array $items, string $stockType, string $priceTyp
|
||||
return [$variant->id => $price?->price ?? 0];
|
||||
});
|
||||
|
||||
$capitalPrices = $variants->mapWithKeys(function (ProductVariant $variant) {
|
||||
$capitalPriceType = $stockType === ProductStockQuality::REJECT->value
|
||||
? PriceType::REJECT_CAPITAL
|
||||
: PriceType::CAPITAL;
|
||||
|
||||
$capitalPrices = $variants->mapWithKeys(function (ProductVariant $variant) use ($capitalPriceType) {
|
||||
$price = $variant->productPrices
|
||||
->first(fn ($p) => $p->type === PriceType::CAPITAL);
|
||||
->first(fn ($p) => $p->type === $capitalPriceType);
|
||||
|
||||
return [$variant->id => $price?->price ?? 0];
|
||||
});
|
||||
|
||||
@ -41,11 +41,11 @@ public function getForRestock(): array
|
||||
|
||||
if ($allVariantIds !== []) {
|
||||
$mediaByVariant = Media::query()
|
||||
->whereIn('mediable_id', $allVariantIds)
|
||||
->where('mediable_type', ProductVariant::class)
|
||||
->whereIn('model_id', $allVariantIds)
|
||||
->where('model_type', ProductVariant::class)
|
||||
->where('collection_name', 'images')
|
||||
->get()
|
||||
->groupBy('mediable_id');
|
||||
->groupBy('model_id');
|
||||
} else {
|
||||
$mediaByVariant = collect();
|
||||
}
|
||||
@ -62,7 +62,7 @@ public function getForRestock(): array
|
||||
$variant->capital_price = $capitalPrice?->price ?? 0;
|
||||
|
||||
$rejectPrice = $variant->productPrices
|
||||
->first(fn ($price) => $price->type === PriceType::REJECT);
|
||||
->first(fn ($price) => $price->type === PriceType::REJECT_CAPITAL);
|
||||
$variant->reject_price = $rejectPrice?->price ?? 0;
|
||||
});
|
||||
})->toArray();
|
||||
@ -84,11 +84,11 @@ public function getForTransaction(): array
|
||||
|
||||
if ($allVariantIds !== []) {
|
||||
$mediaByVariant = Media::query()
|
||||
->whereIn('mediable_id', $allVariantIds)
|
||||
->where('mediable_type', ProductVariant::class)
|
||||
->whereIn('model_id', $allVariantIds)
|
||||
->where('model_type', ProductVariant::class)
|
||||
->where('collection_name', 'images')
|
||||
->get()
|
||||
->groupBy('mediable_id');
|
||||
->groupBy('model_id');
|
||||
} else {
|
||||
$mediaByVariant = collect();
|
||||
}
|
||||
|
||||
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
// 1. product_prices: rename 'reject' → 'reject_selling', then add 'reject_capital' rows
|
||||
DB::table('product_prices')
|
||||
->where('type', 'reject')
|
||||
->update(['type' => 'reject_selling']);
|
||||
|
||||
// Insert reject_capital rows (price = 0) for each variant that now has reject_selling
|
||||
$rejectSellingPrices = DB::table('product_prices')
|
||||
->where('type', 'reject_selling')
|
||||
->get();
|
||||
|
||||
foreach ($rejectSellingPrices as $row) {
|
||||
DB::table('product_prices')->insert([
|
||||
'variant_id' => $row->variant_id,
|
||||
'type' => 'reject_capital',
|
||||
'price' => 0,
|
||||
'created_at' => $row->created_at,
|
||||
'updated_at' => $row->updated_at,
|
||||
]);
|
||||
}
|
||||
|
||||
// 2. orders: rename 'reject' → 'reject_selling'
|
||||
DB::table('orders')
|
||||
->where('price_type', 'reject')
|
||||
->update(['price_type' => 'reject_selling']);
|
||||
|
||||
// 3. Modify enum columns to reflect new values (MySQL only)
|
||||
if (DB::getDriverName() === 'mysql') {
|
||||
DB::statement("ALTER TABLE product_prices MODIFY COLUMN type ENUM('distributor','agent','sub_agent','wholesale','retail','tiktok','shopee','capital','reject_capital','reject_selling') NOT NULL");
|
||||
DB::statement("ALTER TABLE orders MODIFY COLUMN price_type ENUM('distributor','agent','sub_agent','wholesale','retail','tiktok','shopee','capital','reject_capital','reject_selling') NOT NULL");
|
||||
}
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
// Reverse: rename back and clean up
|
||||
DB::table('product_prices')
|
||||
->where('type', 'reject_capital')
|
||||
->delete();
|
||||
|
||||
DB::table('product_prices')
|
||||
->where('type', 'reject_selling')
|
||||
->update(['type' => 'reject']);
|
||||
|
||||
DB::table('orders')
|
||||
->where('price_type', 'reject_selling')
|
||||
->update(['price_type' => 'reject']);
|
||||
|
||||
if (DB::getDriverName() === 'mysql') {
|
||||
DB::statement("ALTER TABLE product_prices MODIFY COLUMN type ENUM('distributor','agent','sub_agent','wholesale','retail','tiktok','shopee','capital','reject') NOT NULL");
|
||||
DB::statement("ALTER TABLE orders MODIFY COLUMN price_type ENUM('distributor','agent','sub_agent','wholesale','retail','tiktok','shopee','capital','reject') NOT NULL");
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -10,21 +10,21 @@ export function NotificationPermissionPrompt() {
|
||||
usePushNotification();
|
||||
|
||||
useEffect(() => {
|
||||
if (!isSupported || hasRequested.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Notification.permission !== 'default') {
|
||||
if (!isSupported || hasRequested.current || !vapidPublicKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
hasRequested.current = true;
|
||||
|
||||
void requestPermission().then(async (result) => {
|
||||
if (result === 'granted' && vapidPublicKey) {
|
||||
await subscribe(vapidPublicKey);
|
||||
}
|
||||
});
|
||||
if (Notification.permission === 'default') {
|
||||
void requestPermission().then(async (result) => {
|
||||
if (result === 'granted') {
|
||||
await subscribe(vapidPublicKey);
|
||||
}
|
||||
});
|
||||
} else if (Notification.permission === 'granted') {
|
||||
void subscribe(vapidPublicKey);
|
||||
}
|
||||
}, [isSupported, requestPermission, subscribe, vapidPublicKey]);
|
||||
|
||||
return null;
|
||||
|
||||
@ -68,7 +68,7 @@ type Props = {
|
||||
priceTypeOptions: TransactionCreateData['priceTypeOptions'];
|
||||
};
|
||||
|
||||
const SELLING_PRICE_TYPES = ['distributor', 'agent', 'sub_agent', 'wholesale', 'retail', 'tiktok', 'shopee'];
|
||||
const SELLING_PRICE_TYPES = ['distributor', 'agent', 'sub_agent', 'wholesale', 'retail', 'tiktok', 'shopee', 'reject_selling'];
|
||||
|
||||
export default function TransactionCreate({
|
||||
products,
|
||||
@ -181,8 +181,8 @@ export default function TransactionCreate({
|
||||
|
||||
useEffect(() => {
|
||||
if (stockType === 'reject') {
|
||||
setPriceType('reject');
|
||||
} else if (priceType === 'reject') {
|
||||
setPriceType('reject_selling');
|
||||
} else if (priceType === 'reject_selling') {
|
||||
setPriceType('retail');
|
||||
}
|
||||
}, [stockType]);
|
||||
@ -191,7 +191,7 @@ export default function TransactionCreate({
|
||||
|
||||
const availablePriceTypes = useMemo(() => {
|
||||
if (stockType === 'reject') {
|
||||
return priceTypeOptions.filter((o) => o.value === 'reject');
|
||||
return priceTypeOptions.filter((o) => o.value === 'reject_selling');
|
||||
}
|
||||
|
||||
return priceTypeOptions.filter((o) => SELLING_PRICE_TYPES.includes(o.value));
|
||||
@ -206,7 +206,7 @@ export default function TransactionCreate({
|
||||
}
|
||||
|
||||
if (stockType === 'reject') {
|
||||
return variant.prices?.reject ?? 0;
|
||||
return variant.prices?.reject_selling ?? 0;
|
||||
}
|
||||
|
||||
return variant.prices?.[priceType] ?? 0;
|
||||
@ -284,7 +284,7 @@ export default function TransactionCreate({
|
||||
return {
|
||||
stock_type: stockType,
|
||||
channel,
|
||||
price_type: stockType === 'reject' ? 'reject' : priceType,
|
||||
price_type: stockType === 'reject' ? 'reject_selling' : priceType,
|
||||
payment_type: paymentType,
|
||||
customer_id: customerId,
|
||||
marketing_id: marketingId,
|
||||
@ -443,7 +443,7 @@ export default function TransactionCreate({
|
||||
) : (
|
||||
formatCurrency(
|
||||
stockType === 'reject'
|
||||
? (variant.prices?.reject ?? 0)
|
||||
? (variant.prices?.reject_selling ?? 0)
|
||||
: (variant.prices?.[priceType] ?? 0),
|
||||
)
|
||||
)}
|
||||
|
||||
@ -67,7 +67,7 @@ type Props = {
|
||||
priceTypeOptions: TransactionCreateData['priceTypeOptions'];
|
||||
};
|
||||
|
||||
const SELLING_PRICE_TYPES = ['distributor', 'agent', 'sub_agent', 'wholesale', 'retail', 'tiktok', 'shopee'];
|
||||
const SELLING_PRICE_TYPES = ['distributor', 'agent', 'sub_agent', 'wholesale', 'retail', 'tiktok', 'shopee', 'reject_selling'];
|
||||
|
||||
export default function TransactionEdit({
|
||||
transaction,
|
||||
@ -134,8 +134,8 @@ export default function TransactionEdit({
|
||||
|
||||
useEffect(() => {
|
||||
if (stockType === 'reject') {
|
||||
setPriceType('reject');
|
||||
} else if (priceType === 'reject') {
|
||||
setPriceType('reject_selling');
|
||||
} else if (priceType === 'reject_selling') {
|
||||
setPriceType('retail');
|
||||
}
|
||||
}, [stockType]);
|
||||
@ -162,7 +162,7 @@ export default function TransactionEdit({
|
||||
|
||||
const availablePriceTypes = useMemo(() => {
|
||||
if (stockType === 'reject') {
|
||||
return priceTypeOptions.filter((o) => o.value === 'reject');
|
||||
return priceTypeOptions.filter((o) => o.value === 'reject_selling');
|
||||
}
|
||||
|
||||
return priceTypeOptions.filter((o) => SELLING_PRICE_TYPES.includes(o.value));
|
||||
@ -177,7 +177,7 @@ export default function TransactionEdit({
|
||||
}
|
||||
|
||||
if (stockType === 'reject') {
|
||||
return variant.prices?.reject ?? 0;
|
||||
return variant.prices?.reject_selling ?? 0;
|
||||
}
|
||||
|
||||
return variant.prices?.[priceType] ?? 0;
|
||||
@ -255,7 +255,7 @@ export default function TransactionEdit({
|
||||
return {
|
||||
stock_type: stockType,
|
||||
channel,
|
||||
price_type: stockType === 'reject' ? 'reject' : priceType,
|
||||
price_type: stockType === 'reject' ? 'reject_selling' : priceType,
|
||||
payment_type: paymentType,
|
||||
customer_id: customerId,
|
||||
marketing_id: marketingId,
|
||||
@ -423,7 +423,7 @@ export default function TransactionEdit({
|
||||
) : (
|
||||
formatCurrency(
|
||||
stockType === 'reject'
|
||||
? (variant.prices?.reject ?? 0)
|
||||
? (variant.prices?.reject_selling ?? 0)
|
||||
: (variant.prices?.[priceType] ?? 0),
|
||||
)
|
||||
)}
|
||||
|
||||
@ -43,7 +43,8 @@ const PRICE_TYPES = [
|
||||
{ key: 'tiktok', label: 'TikTok' },
|
||||
{ key: 'shopee', label: 'Shopee' },
|
||||
{ key: 'capital', label: 'Modal' },
|
||||
{ key: 'reject', label: 'Reject' },
|
||||
{ key: 'reject_capital', label: 'Reject Modal' },
|
||||
{ key: 'reject_selling', label: 'Reject Jual' },
|
||||
];
|
||||
|
||||
function createEmptyPrices(): Array<{ type: string; price: number }> {
|
||||
|
||||
@ -61,7 +61,8 @@ const PRICE_TYPES = [
|
||||
{ key: 'tiktok', label: 'TikTok' },
|
||||
{ key: 'shopee', label: 'Shopee' },
|
||||
{ key: 'capital', label: 'Modal' },
|
||||
{ key: 'reject', label: 'Reject' },
|
||||
{ key: 'reject_capital', label: 'Reject Modal' },
|
||||
{ key: 'reject_selling', label: 'Reject Jual' },
|
||||
];
|
||||
|
||||
function createEmptyPrices(): Array<{ type: string; price: number }> {
|
||||
@ -104,6 +105,13 @@ export default function ProductEdit({ product, categories }: Props) {
|
||||
product.description ?? '',
|
||||
);
|
||||
|
||||
function normalizePrices(serverPrices: Array<{ type: string; price: number }>): Array<{ type: string; price: number }> {
|
||||
return PRICE_TYPES.map((pt) => {
|
||||
const existing = serverPrices.find((p) => p.type === pt.key);
|
||||
return { type: pt.key, price: existing?.price ?? 0 };
|
||||
});
|
||||
}
|
||||
|
||||
const serverVariants: VariantState[] = product.product_variants.map(
|
||||
(v) => ({
|
||||
id: v.id,
|
||||
@ -116,7 +124,7 @@ export default function ProductEdit({ product, categories }: Props) {
|
||||
url: v.photo_urls[i] ?? null,
|
||||
})),
|
||||
uploading: false,
|
||||
prices: v.prices.length > 0 ? v.prices : createEmptyPrices(),
|
||||
prices: normalizePrices(v.prices),
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@ -35,7 +35,8 @@ const PRICE_TYPES = [
|
||||
{ key: 'tiktok', label: 'TikTok' },
|
||||
{ key: 'shopee', label: 'Shopee' },
|
||||
{ key: 'capital', label: 'Modal' },
|
||||
{ key: 'reject', label: 'Reject' },
|
||||
{ key: 'reject_capital', label: 'Reject Modal' },
|
||||
{ key: 'reject_selling', label: 'Reject Jual' },
|
||||
];
|
||||
|
||||
export default function ProductVariantEdit({ variant }: Props) {
|
||||
@ -53,14 +54,15 @@ export default function ProductVariantEdit({ variant }: Props) {
|
||||
const [prices, setPrices] = useState<
|
||||
Array<{ type: string; price: number }>
|
||||
>(
|
||||
variant.prices.length > 0
|
||||
? variant.prices
|
||||
: PRICE_TYPES.map((pt) => ({ type: pt.key, price: 0 })),
|
||||
PRICE_TYPES.map((pt) => {
|
||||
const existing = variant.prices.find((p) => p.type === pt.key);
|
||||
return { type: pt.key, price: existing?.price ?? 0 };
|
||||
}),
|
||||
);
|
||||
|
||||
function updatePrice(priceIndex: number, value: number) {
|
||||
function updatePrice(priceType: string, value: number) {
|
||||
setPrices((prev) =>
|
||||
prev.map((p, i) => (i === priceIndex ? { ...p, price: value } : p)),
|
||||
prev.map((p) => (p.type === priceType ? { ...p, price: value } : p)),
|
||||
);
|
||||
}
|
||||
|
||||
@ -200,7 +202,9 @@ export default function ProductVariantEdit({ variant }: Props) {
|
||||
<CardContent>
|
||||
<div className="grid grid-cols-2 gap-4 md:grid-cols-3">
|
||||
{PRICE_TYPES.map(
|
||||
(priceType, priceIndex) => (
|
||||
(priceType) => {
|
||||
const priceEntry = prices.find((p) => p.type === priceType.key);
|
||||
return (
|
||||
<div
|
||||
key={priceType.key}
|
||||
className="grid gap-2"
|
||||
@ -214,15 +218,13 @@ export default function ProductVariantEdit({ variant }: Props) {
|
||||
</Label>
|
||||
<RupiahInput
|
||||
value={
|
||||
prices[
|
||||
priceIndex
|
||||
]?.price ?? 0
|
||||
priceEntry?.price ?? 0
|
||||
}
|
||||
onValueChange={(
|
||||
val,
|
||||
) =>
|
||||
updatePrice(
|
||||
priceIndex,
|
||||
priceType.key,
|
||||
val,
|
||||
)
|
||||
}
|
||||
@ -230,12 +232,13 @@ export default function ProductVariantEdit({ variant }: Props) {
|
||||
<InputError
|
||||
message={
|
||||
errors[
|
||||
`prices.${priceIndex}.price`
|
||||
`prices.${priceType.key}.price`
|
||||
]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
);
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
|
||||
@ -45,7 +45,8 @@ function makeValidProductPayload(array $overrides = []): array
|
||||
['type' => 'tiktok', 'price' => 16000],
|
||||
['type' => 'shopee', 'price' => 16500],
|
||||
['type' => 'capital', 'price' => 8000],
|
||||
['type' => 'reject', 'price' => 5000],
|
||||
['type' => 'reject_capital', 'price' => 5000],
|
||||
['type' => 'reject_selling', 'price' => 6000],
|
||||
],
|
||||
],
|
||||
],
|
||||
@ -71,7 +72,8 @@ function makeValidSharedPricePayload(array $overrides = []): array
|
||||
['type' => 'tiktok', 'price' => 16000],
|
||||
['type' => 'shopee', 'price' => 16500],
|
||||
['type' => 'capital', 'price' => 8000],
|
||||
['type' => 'reject', 'price' => 5000],
|
||||
['type' => 'reject_capital', 'price' => 5000],
|
||||
['type' => 'reject_selling', 'price' => 6000],
|
||||
],
|
||||
'variants' => [
|
||||
[
|
||||
@ -97,7 +99,8 @@ function allPriceTypes(): array
|
||||
['type' => 'tiktok', 'price' => 16000],
|
||||
['type' => 'shopee', 'price' => 16500],
|
||||
['type' => 'capital', 'price' => 8000],
|
||||
['type' => 'reject', 'price' => 5000],
|
||||
['type' => 'reject_capital', 'price' => 5000],
|
||||
['type' => 'reject_selling', 'price' => 6000],
|
||||
];
|
||||
}
|
||||
|
||||
@ -1946,7 +1949,8 @@ function allPriceTypes(): array
|
||||
['type' => 'tiktok', 'price' => 16000],
|
||||
['type' => 'shopee', 'price' => 16500],
|
||||
['type' => 'capital', 'price' => 8000],
|
||||
['type' => 'reject', 'price' => 5000],
|
||||
['type' => 'reject_capital', 'price' => 5000],
|
||||
['type' => 'reject_selling', 'price' => 6000],
|
||||
];
|
||||
|
||||
$response = $this->post(route('admin.master.products.store'), makeValidProductPayload([
|
||||
@ -1965,9 +1969,10 @@ function allPriceTypes(): array
|
||||
$variant = ProductVariant::where('name', 'Semua Harga')->first();
|
||||
$dbPrices = ProductPrice::where('variant_id', $variant->id)->get();
|
||||
|
||||
expect($dbPrices)->toHaveCount(9);
|
||||
expect($dbPrices)->toHaveCount(10);
|
||||
expect($dbPrices->firstWhere('type', 'distributor')->price)->toBe(10000);
|
||||
expect($dbPrices->firstWhere('type', 'reject')->price)->toBe(5000);
|
||||
expect($dbPrices->firstWhere('type', 'reject_capital')->price)->toBe(5000);
|
||||
expect($dbPrices->firstWhere('type', 'reject_selling')->price)->toBe(6000);
|
||||
});
|
||||
|
||||
test('shared price applies to all variants', function () {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user