Backfill the completed acquisitions, sales, dashboard, pricing, search, public detail, worker, migration, contracts, validation, tests, and implementation-status changes into one verified application slice.
186 lines
4.8 KiB
JavaScript
186 lines
4.8 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
|
|
import { createSaleService } from "../../src/modules/sales/services/sale-service.js";
|
|
|
|
function validInput(overrides = {}) {
|
|
return {
|
|
sellerId: "seller-1",
|
|
inventoryItemId: "inventory-1",
|
|
saleDate: "2026-09-09",
|
|
soldPriceMinor: 2499,
|
|
costBasisMinor: 1200,
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
test("creates a sale through the repository with validated money values", async () => {
|
|
let received;
|
|
const service = createSaleService({
|
|
saleRepository: {
|
|
async createForInventoryItem(input) {
|
|
received = input;
|
|
return {
|
|
status: "CREATED",
|
|
sale: {
|
|
id: "sale-1",
|
|
soldPriceMinor: 2499,
|
|
platformFeesMinor: 100,
|
|
paymentProcessingFeesMinor: 0,
|
|
shippingCostMinor: 0,
|
|
taxesMinor: 0,
|
|
otherFeesMinor: 0,
|
|
},
|
|
saleItem: { costBasisMinor: 1200 },
|
|
};
|
|
},
|
|
},
|
|
});
|
|
|
|
assert.deepEqual(await service.create(validInput()), {
|
|
status: "CREATED",
|
|
sale: {
|
|
id: "sale-1",
|
|
soldPriceMinor: 2499,
|
|
platformFeesMinor: 100,
|
|
paymentProcessingFeesMinor: 0,
|
|
shippingCostMinor: 0,
|
|
taxesMinor: 0,
|
|
otherFeesMinor: 0,
|
|
},
|
|
saleItem: { costBasisMinor: 1200 },
|
|
netProceedsMinor: 2399,
|
|
profitMinor: 1199,
|
|
});
|
|
assert.equal(received.sale.sellerId, "seller-1");
|
|
assert.equal(received.sale.soldPriceMinor, 2499);
|
|
assert.equal(received.costBasisMinor, 1200);
|
|
});
|
|
|
|
test("lists seller sales with derived net proceeds and profit", async () => {
|
|
const service = createSaleService({
|
|
saleRepository: {
|
|
async listBySellerId(sellerId) {
|
|
assert.equal(sellerId, "seller-1");
|
|
return [
|
|
{
|
|
sale: { soldPriceMinor: 3000, shippingCostMinor: 200 },
|
|
saleItem: { costBasisMinor: 1500 },
|
|
inventoryItem: { id: "inventory-1", status: "SOLD" },
|
|
},
|
|
];
|
|
},
|
|
},
|
|
});
|
|
|
|
const [sale] = await service.list({ sellerId: "seller-1" });
|
|
assert.equal(sale.netProceedsMinor, 2800);
|
|
assert.equal(sale.profitMinor, 1300);
|
|
});
|
|
|
|
test("voids an owned sale with a required reason", async () => {
|
|
let received;
|
|
const service = createSaleService({
|
|
saleRepository: {
|
|
async voidForSeller(input) {
|
|
received = input;
|
|
return {
|
|
status: "VOIDED",
|
|
sale: { id: "sale-1", soldPriceMinor: 3000 },
|
|
saleItem: { costBasisMinor: 1500 },
|
|
inventoryItem: { id: "inventory-1", status: "ACTIVE" },
|
|
};
|
|
},
|
|
},
|
|
});
|
|
|
|
const result = await service.void({
|
|
saleId: "sale-1",
|
|
sellerId: "seller-1",
|
|
actorUserId: "user-1",
|
|
reason: " Duplicate sale ",
|
|
});
|
|
|
|
assert.equal(received.reason, "Duplicate sale");
|
|
assert.equal(result.inventoryItem.status, "ACTIVE");
|
|
await assert.rejects(
|
|
() =>
|
|
service.void({
|
|
saleId: "sale-1",
|
|
sellerId: "seller-1",
|
|
actorUserId: "user-1",
|
|
reason: "x",
|
|
}),
|
|
(error) =>
|
|
error.code === "SALE_VOID_REASON_REQUIRED" && error.statusCode === 400,
|
|
);
|
|
});
|
|
|
|
test("creates one sale containing multiple inventory items", async () => {
|
|
let received;
|
|
const service = createSaleService({
|
|
saleRepository: {
|
|
async createForInventoryItems(input) {
|
|
received = input;
|
|
return {
|
|
status: "CREATED",
|
|
sale: { id: "sale-2", soldPriceMinor: 3000 },
|
|
saleItems: input.items,
|
|
saleItem: input.items[0],
|
|
inventoryItems: input.items.map(({ inventoryItemId }) => ({
|
|
id: inventoryItemId,
|
|
status: "SOLD",
|
|
})),
|
|
inventoryItem: { id: input.items[0].inventoryItemId, status: "SOLD" },
|
|
};
|
|
},
|
|
},
|
|
});
|
|
|
|
const result = await service.create({
|
|
sellerId: "seller-1",
|
|
saleDate: "2026-09-09",
|
|
items: [
|
|
{
|
|
inventoryItemId: "inventory-1",
|
|
soldPriceMinor: 1200,
|
|
costBasisMinor: 500,
|
|
},
|
|
{
|
|
inventoryItemId: "inventory-2",
|
|
soldPriceMinor: 1800,
|
|
costBasisMinor: 700,
|
|
},
|
|
],
|
|
});
|
|
|
|
assert.equal(received.sale.soldPriceMinor, 3000);
|
|
assert.equal(received.items.length, 2);
|
|
assert.equal(result.profitMinor, 1800);
|
|
});
|
|
|
|
test("maps missing and already-sold inventory to application errors", async () => {
|
|
for (const result of [
|
|
{ status: "NOT_FOUND", code: "INVENTORY_NOT_FOUND", statusCode: 404 },
|
|
{
|
|
status: "NOT_ACTIVE",
|
|
code: "INVENTORY_NOT_AVAILABLE_FOR_SALE",
|
|
statusCode: 409,
|
|
},
|
|
]) {
|
|
const service = createSaleService({
|
|
saleRepository: {
|
|
async createForInventoryItem() {
|
|
return result;
|
|
},
|
|
},
|
|
});
|
|
|
|
await assert.rejects(
|
|
() => service.create(validInput()),
|
|
(error) =>
|
|
error.code === result.code && error.statusCode === result.statusCode,
|
|
);
|
|
}
|
|
});
|