feat: reconcile application vertical slices
Backfill the completed acquisitions, sales, dashboard, pricing, search, public detail, worker, migration, contracts, validation, tests, and implementation-status changes into one verified application slice.
This commit is contained in:
@@ -1,77 +1,137 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
|
||||
import { createPricingService } from '../../src/modules/pricing/services/pricing-service.js';
|
||||
import { createPricingService } from "../../src/modules/pricing/services/pricing-service.js";
|
||||
|
||||
test('records an owned pricing observation and calculates a valuation', async () => {
|
||||
test("records an owned pricing observation and calculates a valuation", async () => {
|
||||
const service = createPricingService({
|
||||
pricingRepository: {
|
||||
async addObservationForSeller({ observation, sellerId }) {
|
||||
assert.equal(sellerId, 'seller-1');
|
||||
return { status: 'CREATED', observation };
|
||||
assert.equal(sellerId, "seller-1");
|
||||
return { status: "CREATED", observation };
|
||||
},
|
||||
async markOutliersForSeller() {
|
||||
return { status: 'UPDATED' };
|
||||
return { status: "UPDATED" };
|
||||
},
|
||||
async calculateForSeller() {
|
||||
return { status: 'CALCULATED', valuation: { valueMinor: 2500 }, observations: [] };
|
||||
return {
|
||||
status: "CALCULATED",
|
||||
valuation: { valueMinor: 2500 },
|
||||
observations: [],
|
||||
};
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const observation = await service.addObservation({
|
||||
sellerId: 'seller-1', productId: 'product-1', inventoryItemId: 'inventory-1',
|
||||
providerId: 'manual', priceMinor: 2500, sourceIdentifier: 'source-1', conditionId: 'condition-1',
|
||||
sellerId: "seller-1",
|
||||
productId: "product-1",
|
||||
inventoryItemId: "inventory-1",
|
||||
providerId: "manual",
|
||||
priceMinor: 2500,
|
||||
sourceIdentifier: "source-1",
|
||||
conditionId: "condition-1",
|
||||
});
|
||||
assert.equal(observation.priceMinor, 2500);
|
||||
const valuation = await service.calculate({ sellerId: 'seller-1', inventoryItemId: 'inventory-1' });
|
||||
const valuation = await service.calculate({
|
||||
sellerId: "seller-1",
|
||||
inventoryItemId: "inventory-1",
|
||||
});
|
||||
assert.equal(valuation.valuation.valueMinor, 2500);
|
||||
});
|
||||
|
||||
test('requires a reason for an audited market-value override', async () => {
|
||||
const service = createPricingService({ pricingRepository: { async createOverride() { throw new Error('should not run'); } } });
|
||||
test("requires a reason for an audited market-value override", async () => {
|
||||
const service = createPricingService({
|
||||
pricingRepository: {
|
||||
async createOverride() {
|
||||
throw new Error("should not run");
|
||||
},
|
||||
},
|
||||
});
|
||||
await assert.rejects(
|
||||
() => service.override({ sellerId: 'seller-1', actorUserId: 'user-1', inventoryItemId: 'inventory-1', valueMinor: 2000, reason: 'x' }),
|
||||
(error) => error.code === 'OVERRIDE_REASON_REQUIRED' && error.statusCode === 400,
|
||||
() =>
|
||||
service.override({
|
||||
sellerId: "seller-1",
|
||||
actorUserId: "user-1",
|
||||
inventoryItemId: "inventory-1",
|
||||
valueMinor: 2000,
|
||||
reason: "x",
|
||||
}),
|
||||
(error) =>
|
||||
error.code === "OVERRIDE_REASON_REQUIRED" && error.statusCode === 400,
|
||||
);
|
||||
});
|
||||
|
||||
test('fails clearly when a requested pricing provider is unavailable', async () => {
|
||||
test("fails clearly when a requested pricing provider is unavailable", async () => {
|
||||
const service = createPricingService({
|
||||
pricingRepository: {},
|
||||
pricingProviderRegistry: { get() { return null; } },
|
||||
pricingProviderRegistry: {
|
||||
get() {
|
||||
return null;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await assert.rejects(
|
||||
() => service.refresh({ sellerId: 'seller-1', inventoryItemId: 'inventory-1', providerId: 'missing' }),
|
||||
(error) => error.code === 'PRICING_PROVIDER_UNAVAILABLE' && error.statusCode === 503,
|
||||
() =>
|
||||
service.refresh({
|
||||
sellerId: "seller-1",
|
||||
inventoryItemId: "inventory-1",
|
||||
providerId: "missing",
|
||||
}),
|
||||
(error) =>
|
||||
error.code === "PRICING_PROVIDER_UNAVAILABLE" && error.statusCode === 503,
|
||||
);
|
||||
});
|
||||
|
||||
test('enqueues a seller-scoped pricing refresh and reads its status', async () => {
|
||||
test("enqueues a seller-scoped pricing refresh and reads its status", async () => {
|
||||
const service = createPricingService({
|
||||
pricingRepository: {},
|
||||
pricingRefreshJobRepository: {
|
||||
async create(input) { return { id: 'job-1', status: 'PENDING', ...input }; },
|
||||
async findByIdForSeller(id, sellerId) { return { id, sellerId, status: 'COMPLETED' }; },
|
||||
async create(input) {
|
||||
return { id: "job-1", status: "PENDING", ...input };
|
||||
},
|
||||
async findByIdForSeller(id, sellerId) {
|
||||
return { id, sellerId, status: "COMPLETED" };
|
||||
},
|
||||
},
|
||||
providerMappingRepository: {
|
||||
async findActiveForSeller() {
|
||||
return { providerId: "mapped-provider" };
|
||||
},
|
||||
},
|
||||
providerMappingRepository: { async findActiveForSeller() { return { providerId: 'mapped-provider' }; } },
|
||||
});
|
||||
|
||||
const job = await service.enqueueRefresh({ sellerId: 'seller-1', inventoryItemId: 'item-1', providerId: 'provider-1', productId: 'product-1', conditionId: 'condition-1' });
|
||||
assert.equal(job.status, 'PENDING');
|
||||
assert.equal(job.providerId, 'mapped-provider');
|
||||
assert.equal((await service.getJob({ sellerId: 'seller-1', jobId: job.id })).status, 'COMPLETED');
|
||||
const job = await service.enqueueRefresh({
|
||||
sellerId: "seller-1",
|
||||
inventoryItemId: "item-1",
|
||||
providerId: "provider-1",
|
||||
productId: "product-1",
|
||||
conditionId: "condition-1",
|
||||
});
|
||||
assert.equal(job.status, "PENDING");
|
||||
assert.equal(job.providerId, "mapped-provider");
|
||||
assert.equal(
|
||||
(await service.getJob({ sellerId: "seller-1", jobId: job.id })).status,
|
||||
"COMPLETED",
|
||||
);
|
||||
});
|
||||
|
||||
test('lists and retries seller-scoped failed pricing jobs', async () => {
|
||||
test("lists and retries seller-scoped failed pricing jobs", async () => {
|
||||
const service = createPricingService({
|
||||
pricingRepository: {},
|
||||
pricingRefreshJobRepository: {
|
||||
async listForSeller() { return [{ id: 'job-1', status: 'FAILED' }]; },
|
||||
async retryForSeller() { return { id: 'job-1', status: 'PENDING' }; },
|
||||
async listForSeller() {
|
||||
return [{ id: "job-1", status: "FAILED" }];
|
||||
},
|
||||
async retryForSeller() {
|
||||
return { id: "job-1", status: "PENDING" };
|
||||
},
|
||||
},
|
||||
});
|
||||
assert.equal((await service.listJobs({ sellerId: 'seller-1' })).length, 1);
|
||||
assert.equal((await service.retryJob({ sellerId: 'seller-1', jobId: 'job-1' })).status, 'PENDING');
|
||||
});
|
||||
assert.equal((await service.listJobs({ sellerId: "seller-1" })).length, 1);
|
||||
assert.equal(
|
||||
(await service.retryJob({ sellerId: "seller-1", jobId: "job-1" })).status,
|
||||
"PENDING",
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user