Skip to content
This repository has been archived by the owner on Dec 18, 2024. It is now read-only.

Commit

Permalink
match transfer changes (#534)
Browse files Browse the repository at this point in the history
* refactor(match-transfer): extract helpers

* feat(match-transfer): use original order deadline

Did not remove deadlineOverride, so now the priority order goes
deadlineOverride > original receiver order deadline > branch rent
period.

* feat(match-transfer): use receiver branch

This fixes a few problems:
- When receiving a book, it was handed out using the sender's branch,
not the receiver's. This impacted which deadline was used, and which
branch the customeritem was registered on.
- Set movedFrom for match-receive orders to the receiver's original
order.
- Fix bug with movedTo/-From where the order which was moved from would
not get an update to its movedTo. This was caused by a type discrepancy
where a string item-ID was checked against an ObjectId, which always
failed. The root cause was a lack of recursion in the
MongooseSchemaCreator.transformObject-function, where objects nested in
arrays were not transformed.

* feat(match-transfer): attach customeritem to orders

* fix(DateService): fix flakiness in UTC-diff-zone

The test for betweenHours() failed between 00:00 and 02:00 in Norwegian
summer time (UTC+2) because the wrong day was used. Fixed by
constructing dates with the supplied timezone.

* fix(match-operation): remove unneccecary check

* fix(match-generate): add missing ObjectID conversion

---------

Co-authored-by: Adrian Andersen <adrianandersen@protonmail.com>
  • Loading branch information
LarsSelbekk and AdrianAndersen authored Aug 8, 2024
1 parent 9d97490 commit 6126536
Show file tree
Hide file tree
Showing 9 changed files with 334 additions and 169 deletions.
14 changes: 12 additions & 2 deletions src/blc/date.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,14 +159,24 @@ describe("DateService", () => {

describe("betweenHours()", () => {
it("should return true if date is between from hour and to hour", () => {
const date = moment().hour(12).minute(15).seconds(22).toDate();
const date = moment()
.tz("Europe/Oslo")
.hour(12)
.minute(15)
.seconds(22)
.toDate();

return expect(dateService.betweenHours(date, 8, 18, "Europe/Oslo")).to.be
.true;
});

it("should return false if date is not between from hour and to hour", () => {
const date = moment().hour(7).minute(15).seconds(22).toDate();
const date = moment()
.tz("Europe/Oslo")
.hour(7)
.minute(15)
.seconds(22)
.toDate();

return expect(dateService.betweenHours(date, 8, 18, "Europe/Oslo")).to.be
.false;
Expand Down
4 changes: 2 additions & 2 deletions src/blc/date.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ export class DateService {
toHour: number,
location: MomentLocation,
): boolean {
const from = moment.tz().hour(fromHour).minute(0).second(0);
const to = moment.tz().hour(toHour).minute(0).second(0);
const from = moment.tz(location).hour(fromHour).minute(0).second(0);
const to = moment.tz(location).hour(toHour).minute(0).second(0);

return this.between(date, from.toDate(), to.toDate(), location);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ import { BlCollectionName } from "../../bl-collection";
import { userDetailSchema } from "../../user-detail/user-detail.schema";

export class OrderToCustomerItemGenerator {
constructor(private _userDetailStorage?: BlDocumentStorage<UserDetail>) {
this._userDetailStorage = this._userDetailStorage
? this._userDetailStorage
: new BlDocumentStorage(BlCollectionName.UserDetails, userDetailSchema);
private _userDetailStorage: BlDocumentStorage<UserDetail>;

constructor(userDetailStorage?: BlDocumentStorage<UserDetail>) {
this._userDetailStorage =
userDetailStorage ??
new BlDocumentStorage(BlCollectionName.UserDetails, userDetailSchema);
}

public async generate(order: Order): Promise<CustomerItem[]> {
Expand All @@ -23,8 +25,6 @@ export class OrderToCustomerItemGenerator {
return [];
}

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const customerDetail = await this._userDetailStorage.get(order.customer);

for (const orderItem of order.orderItems) {
Expand All @@ -34,9 +34,7 @@ export class OrderToCustomerItemGenerator {
order,
orderItem,
);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
customerItem.viewableFor = [customerDetail.blid];
customerItem.viewableFor = [customerDetail.blid!];
customerItems.push(customerItem);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ export async function getMatchableSenders(
aggregatedSenders = (await customerItemStorage.aggregate([
{
$match: {
customer: { $in: aggregatedSenders.map((sender) => sender.id) },
customer: {
$in: aggregatedSenders.map((sender) => new ObjectId(sender.id)),
},
returned: false,
buyout: false,
cancel: false,
Expand All @@ -109,6 +111,7 @@ export async function getMatchableSenders(
groupByCustomerStep,
])) as { id: string; items: string[] }[];
}
console.log("aggSenders: ", aggregatedSenders);

return aggregatedSenders.map((sender) => ({
id: sender.id,
Expand Down
142 changes: 94 additions & 48 deletions src/collections/match/operations/match-operation-utils.ts
Original file line number Diff line number Diff line change
@@ -1,75 +1,82 @@
import {
BlError,
Match,
Branch,
CustomerItem,
Item,
Match,
Order,
OrderItem,
} from "@boklisten/bl-model";

import { isNullish } from "../../../helper/typescript-helpers";
import { SEDbQuery } from "../../../query/se.db-query";
import { BlDocumentStorage } from "../../../storage/blDocumentStorage";
import { BlCollectionName } from "../../bl-collection";
import { branchSchema } from "../../branch/branch.schema";
import { itemSchema } from "../../item/item.schema";
import { OrderActive } from "../../order/helpers/order-active/order-active";

export async function createMatchOrder(
export async function createMatchReceiveOrder(
customerItem: CustomerItem,
userDetailId: string,
isSender: boolean,
itemStorage: BlDocumentStorage<Item>,
branchStorage: BlDocumentStorage<Branch>,
deadlineOverrides?: { [item: string]: string },
): Promise<Order> {
const itemStorage = new BlDocumentStorage<Item>(
BlCollectionName.Items,
itemSchema,
);
const item = await itemStorage.get(customerItem.item);

if (!item) {
throw new BlError("Failed to get item");
}

const branchStorage = new BlDocumentStorage<Branch>(
BlCollectionName.Branches,
branchSchema,
);
if (isNullish(customerItem.handoutInfo)) {
throw new BlError("No handoutInfo for customerItem").code(200);
interface OriginalOrderInfo {
order: Order;
relevantOrderItem: OrderItem;
}
const branch = await branchStorage.get(customerItem.handoutInfo.handoutById);
let originalReceiverOrderInfo: OriginalOrderInfo | undefined = undefined;

const newRentPeriod = branch?.paymentInfo?.rentPeriods?.[0];
const orderActive = new OrderActive();
originalReceiverOrderInfo = (await orderActive.getActiveOrders(userDetailId))
.map((order) => ({
order,
relevantOrderItem: order.orderItems.find(
(orderItem) =>
orderActive.isOrderItemActive(orderItem) &&
orderItem.item === customerItem.item &&
orderItem.type === "rent",
),
}))
.find(({ relevantOrderItem }) => relevantOrderItem !== undefined) as
| OriginalOrderInfo
| undefined;

if (!newRentPeriod?.date) {
throw new BlError("Rent period not set for branch");
if (!originalReceiverOrderInfo) {
throw new BlError("No receiver order for match transfer item").code(200);
}
const branch = await branchStorage.get(
originalReceiverOrderInfo.order.branch,
);

if (newRentPeriod.date === customerItem.deadline) {
throw new BlError("Branch rent period is same is customer item deadline");
}
const movedFromOrder = originalReceiverOrderInfo.order.id;

let movedFromOrder = undefined;

if (!isSender) {
const orderActive = new OrderActive();
const activeReceiverOrders =
await orderActive.getActiveOrders(userDetailId);
const originalReceiverOrder = activeReceiverOrders.find((order) =>
order.orderItems
.filter((orderItem) => orderActive.isOrderItemActive(orderItem))
.some((orderItem) => orderItem.item === customerItem.item),
);
if (originalReceiverOrder) {
movedFromOrder = originalReceiverOrder.id;
}
const relevantDeadlineOverride = deadlineOverrides?.[item.id];
const deadlineOverride = relevantDeadlineOverride
? new Date(relevantDeadlineOverride)
: undefined;
const originalOrderDeadline =
originalReceiverOrderInfo.relevantOrderItem.info?.to;
const branchRentDeadline = branch.paymentInfo?.rentPeriods?.[0]?.date;

let deadline =
deadlineOverride ?? originalOrderDeadline ?? branchRentDeadline;

if (!deadline) {
throw new BlError(
"Cannot set deadline: no rent period for branch, no original order deadline and no override",
).code(200);
}
const deadlineOverride = deadlineOverrides?.[item.id];
// This is necessary because it's not actually a date in the database, and thus the type is wrong.
// It might be solved in the future by Zod or some other strict parser/validation.
deadline = new Date(deadline);

return {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// @ts-expect-error id will be auto-generated
id: undefined,
placed: true,
payments: [],
Expand All @@ -79,23 +86,19 @@ export async function createMatchOrder(
byCustomer: true,
pendingSignature: false,
orderItems: [
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
{
movedFromOrder,
item: item.id,
title: item.title,
blid: customerItem.blid,
type: `match-${isSender ? "deliver" : "receive"}`,
blid: customerItem.blid!,
type: "match-receive",
amount: 0,
unitPrice: 0,
taxRate: 0,
taxAmount: 0,
info: {
from: new Date(),
to: deadlineOverride
? new Date(deadlineOverride)
: newRentPeriod.date,
to: deadline,
numberOfPeriods: 1,
periodType: "semester",
},
Expand All @@ -104,6 +107,49 @@ export async function createMatchOrder(
};
}

export async function createMatchDeliverOrder(
customerItem: CustomerItem,
userDetailId: string,
itemStorage: BlDocumentStorage<Item>,
branchStorage: BlDocumentStorage<Branch>,
): Promise<Order> {
const item = await itemStorage.get(customerItem.item);

if (!item) {
throw new BlError("Failed to get item");
}

if (isNullish(customerItem.handoutInfo)) {
throw new BlError("No handout-info for customerItem").code(200);
}
const branch = await branchStorage.get(customerItem.handoutInfo.handoutById);

return {
// @ts-expect-error id will be auto-generated
id: undefined,
placed: true,
payments: [],
amount: 0,
branch: branch.id,
customer: userDetailId,
byCustomer: true,
pendingSignature: false,
orderItems: [
{
item: item.id,
title: item.title,
blid: customerItem.blid!,
customerItem: customerItem.id,
type: "match-deliver",
amount: 0,
unitPrice: 0,
taxRate: 0,
taxAmount: 0,
},
],
};
}

export async function getAllMatchesForUser(
userDetailId: string,
matchStorage: BlDocumentStorage<Match>,
Expand Down
Loading

0 comments on commit 6126536

Please sign in to comment.