Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions src/api/admin/avalara-customers/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,25 @@ import {
} from "../../../modules/avalara-customer/service";
import { AVALARA_CUSTOMER_MODULE } from "../../../modules/avalara-customer";
import feedAvalaraCustomerCacheWorkflow from "../../../workflows/feed-avalara-customer-cache";
import { z } from "zod";
import {
GetAvalaraCustomersSchema,
PutAvalaraCustomersSchema,
} from "./validators";

type BulkUpdateAvalaraCustomerRequest = {
avalara_customers: BulkUpdateRequest[];
};
type GetAvalaraCustomersType = z.infer<typeof GetAvalaraCustomersSchema>;
type PutAvalaraCustomersType = z.infer<typeof PutAvalaraCustomersSchema>;

export async function GET(
req: MedusaRequest,
req: MedusaRequest<GetAvalaraCustomersType>,
res: MedusaResponse
): Promise<void> {
const avalaraCustomerModuleService: AvalaraCustomerModuleService =
req.scope.resolve(AVALARA_CUSTOMER_MODULE);
const logger = req.scope.resolve(ContainerRegistrationKeys.LOGGER);

try {
const offset = Number(req.query.offset || 0);
const limit = Number(req.query.limit || 10);
const { offset, limit } = req.validatedQuery;

logger.debug(
`GET /admin/avalara-customers - Retrieving avalara customers with offset: ${offset}, limit: ${limit}`
Expand Down Expand Up @@ -60,14 +63,14 @@ export async function GET(
}

export async function PUT(
req: MedusaRequest<BulkUpdateAvalaraCustomerRequest>,
req: MedusaRequest<PutAvalaraCustomersType>,
res: MedusaResponse
): Promise<void> {
const avalaraCustomerModuleService: AvalaraCustomerModuleService =
req.scope.resolve(AVALARA_CUSTOMER_MODULE);
const logger = req.scope.resolve(ContainerRegistrationKeys.LOGGER);

const { avalara_customers } = req.body;
const { avalara_customers } = req.validatedBody;

logger.debug(
`PUT /admin/avalara-customers - Starting bulk update for ${
Expand Down
13 changes: 13 additions & 0 deletions src/api/admin/avalara-customers/validators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { z } from "zod";
import { PaginationSchema } from "../../../utils";

export const GetAvalaraCustomersSchema = PaginationSchema;

export const PutAvalaraCustomersSchema = z.object({
avalara_customers: z.array(
z.object({
customer_id: z.string(),
entity_use_code: z.string(),
})
),
});
19 changes: 11 additions & 8 deletions src/api/admin/avalara-products/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,25 @@ import {
import { AVALARA_PRODUCT_MODULE } from "../../../modules/avalara-product";
import { ContainerRegistrationKeys } from "@medusajs/framework/utils";
import feedAvalaraProductCacheWorkflow from "../../../workflows/feed-avalara-product-cache";
import { z } from "zod";
import {
GetAvalaraProductsSchema,
PutAvalaraProductsSchema,
} from "./validators";

type BulkUpdateAvalaraProductRequest = {
avalara_products: BulkUpdateRequest[];
};
type GetAvalaraProductsType = z.infer<typeof GetAvalaraProductsSchema>;
type PutAvalaraProductsType = z.infer<typeof PutAvalaraProductsSchema>;

export async function GET(
req: MedusaRequest,
req: MedusaRequest<GetAvalaraProductsType>,
res: MedusaResponse
): Promise<void> {
const avalaraProductModuleService: AvalaraProductModuleService =
req.scope.resolve(AVALARA_PRODUCT_MODULE);
const logger = req.scope.resolve(ContainerRegistrationKeys.LOGGER);

try {
const offset = Number(req.query.offset || 0);
const limit = Number(req.query.limit || 10);
const { offset, limit } = req.validatedQuery;

logger.debug(
`GET /admin/avalara-products - Retrieving avalara products with offset: ${offset}, limit: ${limit}`
Expand Down Expand Up @@ -57,14 +60,14 @@ export async function GET(
}

export async function PUT(
req: MedusaRequest<BulkUpdateAvalaraProductRequest>,
req: MedusaRequest<PutAvalaraProductsType>,
res: MedusaResponse
): Promise<void> {
const avalaraProductModuleService: AvalaraProductModuleService =
req.scope.resolve(AVALARA_PRODUCT_MODULE);
const logger = req.scope.resolve(ContainerRegistrationKeys.LOGGER);

const { avalara_products } = req.body;
const { avalara_products } = req.validatedBody;

logger.debug(
`PUT /admin/avalara-products - Starting bulk update for ${
Expand Down
13 changes: 13 additions & 0 deletions src/api/admin/avalara-products/validators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { z } from "zod";
import { PaginationSchema } from "../../../utils";

export const GetAvalaraProductsSchema = PaginationSchema;

export const PutAvalaraProductsSchema = z.object({
avalara_products: z.array(
z.object({
product_id: z.string(),
tax_code: z.string(),
})
),
});
44 changes: 44 additions & 0 deletions src/api/middlewares.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {
defineMiddlewares,
validateAndTransformBody,
validateAndTransformQuery,
} from "@medusajs/framework/http";
import {
GetAvalaraCustomersSchema,
PutAvalaraCustomersSchema,
} from "./admin/avalara-customers/validators";
import {
GetAvalaraProductsSchema,
PutAvalaraProductsSchema,
} from "./admin/avalara-products/validators";
import { PostAvalaraAddressSchema } from "./store/avalara-address/validators";

export default defineMiddlewares({
routes: [
{
matcher: "/admin/avalara-customers",
method: "GET",
middlewares: [validateAndTransformQuery(GetAvalaraCustomersSchema, {})],
},
{
matcher: "/admin/avalara-customers",
method: "PUT",
middlewares: [validateAndTransformBody(PutAvalaraCustomersSchema)],
},
{
matcher: "/admin/avalara-products",
method: "GET",
middlewares: [validateAndTransformQuery(GetAvalaraProductsSchema, {})],
},
{
matcher: "/admin/avalara-products",
method: "PUT",
middlewares: [validateAndTransformBody(PutAvalaraProductsSchema)],
},
{
matcher: "/store/avalara-address",
method: "POST",
middlewares: [validateAndTransformBody(PostAvalaraAddressSchema)],
},
],
});
38 changes: 8 additions & 30 deletions src/api/store/avalara-address/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,28 @@ import { MedusaRequest, MedusaResponse } from "@medusajs/framework";
import { ContainerRegistrationKeys } from "@medusajs/framework/utils";
import { AVATAX_FACTORY_MODULE } from "../../../modules/avatax-factory";
import { AvataxFactoryService } from "../../../modules/avatax-factory/service";
import { AddressValidationInfo } from "avatax/models";
import { z } from "zod";
import { PostAvalaraAddressSchema } from "./validators";

type PostAvalaraAddressType = z.infer<typeof PostAvalaraAddressSchema>;

export async function POST(
req: MedusaRequest<AddressValidationInfo>,
req: MedusaRequest<PostAvalaraAddressType>,
res: MedusaResponse
): Promise<void> {
const avataxFactoryService: AvataxFactoryService = req.scope.resolve(
AVATAX_FACTORY_MODULE
);
const logger = req.scope.resolve(ContainerRegistrationKeys.LOGGER);

const { line1, city, region, country } = req.body;
const addressData = req.validatedBody;

logger.debug(
`POST /store/avalara-address/validate - Validating address: ${JSON.stringify(
req.body
addressData
)}`
);

if (!line1 || !city || !country) {
logger.error(
"POST /store/avalara-address/validate - Missing required fields (line1, city, country)"
);
res.status(400).json({
error: "Missing required fields",
address: req.body,
details:
"The following fields are required: line1, city, and country. For US addresses, region is also required.",
});
return;
}

if (country.toLowerCase() === "us" && !region) {
logger.error(
"POST /store/avalara-address/validate - Missing region for US address"
);
res.status(400).json({
address: req.body,
error: "Missing required field",
details: "For US addresses, the region (state) field is required.",
});
return;
}

try {
const client = avataxFactoryService.getClient();

Expand All @@ -54,7 +32,7 @@ export async function POST(
);

const result = await client.resolveAddressPost({
model: req.body,
model: addressData,
});

logger.debug(
Expand Down
13 changes: 13 additions & 0 deletions src/api/store/avalara-address/validators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { z } from "zod";

export const PostAvalaraAddressSchema = z.object({
line1: z.string().min(1, "Address line 1 is required"),
line2: z.string().optional(),
line3: z.string().optional(),
city: z.string().min(1, "City is required"),
region: z.string().optional(),
country: z.string().min(1, "Country is required"),
postalCode: z.string().optional(),
latitude: z.number().optional(),
longitude: z.number().optional(),
});
8 changes: 0 additions & 8 deletions src/modules/avalara-customer/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,6 @@ export class AvalaraCustomerModuleService extends MedusaService({
for (const customerData of avalara_customers) {
const { customer_id, entity_use_code } = customerData;

if (!customer_id || !entity_use_code) {
results.push({
customer_id,
error: "Both customer_id and entity_use_code are required",
});
continue;
}

try {
const avalaraCustomer = await this.upsertAvalaraCustomer(
customer_id,
Expand Down
9 changes: 0 additions & 9 deletions src/modules/avalara-product/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,6 @@ export class AvalaraProductModuleService extends MedusaService({

for (const productData of avalara_products) {
const { product_id, tax_code } = productData;

if (!product_id || !tax_code) {
results.push({
product_id,
error: "Both product_id and tax_code are required",
});
continue;
}

try {
const avalaraProduct = await this.upsertAvalaraProduct(
product_id,
Expand Down
1 change: 1 addition & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ export * from "./get-package-version";
export * from "./has-address-changed";
export * from "./is-valid-entity-use-code";
export * from "./log-workflow-results";
export * from "./pagination-schema";
export * from "./with-avalara-plugin";
16 changes: 16 additions & 0 deletions src/utils/pagination-schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { z } from "zod";

export const PaginationSchema = z.object({
offset: z.preprocess((val) => {
if (val && typeof val === "string") {
return parseInt(val);
}
return val;
}, z.number().optional().default(0)),
limit: z.preprocess((val) => {
if (val && typeof val === "string") {
return parseInt(val);
}
return val;
}, z.number().optional().default(10)),
});