resolve conflict

This commit is contained in:
hagiye
2026-06-05 14:13:35 +03:00
parent b33517f47d
commit c3e92dbe70
7 changed files with 44 additions and 140 deletions

View File

@@ -82,17 +82,6 @@ export class TrainSchedulingService {
async getEligibleContainerBookings(query: GetEligibleContainerBookingsDto) {
const bookingRepository = this.dataSource.getRepository(Booking);
const queryBuilder = bookingRepository
<<<<<<< HEAD
.createQueryBuilder('booking')
.leftJoinAndSelect('booking.company', 'company')
.leftJoinAndSelect('booking.originYard', 'originYard')
.leftJoinAndSelect('booking.destinationYard', 'destinationYard')
.leftJoinAndSelect('booking.bookingContainers', 'bookingContainer')
.leftJoinAndSelect('bookingContainer.containerType', 'containerType')
.leftJoin(TrainScheduleBooking, 'scheduleBooking', 'scheduleBooking.booking_id = booking.id')
.where('booking.freightType = :freightType', { freightType: 'CONTAINER' })
.andWhere('scheduleBooking.id IS NULL');
=======
.createQueryBuilder("booking")
.leftJoinAndSelect("booking.customer", "customer")
.leftJoinAndSelect("booking.originYard", "originYard")
@@ -106,7 +95,6 @@ export class TrainSchedulingService {
)
.where("booking.freightType = :freightType", { freightType: "CONTAINER" })
.andWhere("scheduleBooking.id IS NULL");
>>>>>>> bd6ad54eea229305a214d06081e0ffd27fe163b8
if (query.originStationId) {
queryBuilder.andWhere("booking.originYardId = :originStationId", {
@@ -144,13 +132,6 @@ export class TrainSchedulingService {
const items: EligibleBookingItem[] = bookings.map((booking) => ({
id: booking.id,
reference: booking.reference,
<<<<<<< HEAD
customer: booking.company?.name ?? booking.company?.email ?? 'Unknown customer',
containerType: booking.bookingContainers
?.map((container) => container.containerType?.label ?? container.containerType?.code ?? 'Container')
.join(', ') ?? 'Container',
quantity: booking.bookingContainers?.reduce((sum, container) => sum + Number(container.quantity ?? 0), 0) ?? 0,
=======
customer:
booking.company?.name ?? booking.company?.email ?? "Unknown customer",
containerType:
@@ -167,7 +148,6 @@ export class TrainSchedulingService {
(sum, container) => sum + Number(container.quantity ?? 0),
0,
) ?? 0,
>>>>>>> bd6ad54eea229305a214d06081e0ffd27fe163b8
weightTons: this.roundTons(booking.cargoTotalWeightVgm),
origin:
booking.originYard?.label ??
@@ -674,17 +654,6 @@ export class TrainSchedulingService {
}
async getContainerTrainScheduleById(id: string) {
<<<<<<< HEAD
const schedule = await this.dataSource.getRepository(TrainSchedule).findOne({
where: { id },
relations: {
trainSet: { locomotive: true, wagons: { wagonType: true, allocations: { booking: true } } },
originStation: true,
destinationStation: true,
scheduleBookings: { booking: { company: true, originYard: true, destinationYard: true } },
},
});
=======
const schedule = await this.dataSource
.getRepository(TrainSchedule)
.findOne({
@@ -701,7 +670,6 @@ export class TrainSchedulingService {
},
},
});
>>>>>>> bd6ad54eea229305a214d06081e0ffd27fe163b8
if (!schedule) {
throw new NotFoundException(`Train schedule ${id} not found`);

View File

@@ -2,16 +2,6 @@ import { Injectable, Logger } from "@nestjs/common";
import { randomUUID } from "crypto";
import { DataSource } from "typeorm";
<<<<<<< HEAD
import { BookingContainer } from '../modules/bookings/entities/booking-container.entity';
import { Booking } from '../modules/bookings/entities/booking.entity';
import { Company } from '../modules/companies/entities/company.entity';
import { Locomotive } from '../modules/locomotives/entities/locomotive.entity';
import { ServiceType } from '../modules/rule-engine/entities/service-type.entity';
import { Yard } from '../modules/rule-engine/entities/yard.entity';
import { WagonType } from '../modules/wagon-types/entities/wagon-type.entity';
import { ContainerType } from '../modules/rule-engine/entities/container-type.entity';
=======
import { BookingContainer } from "../modules/bookings/entities/booking-container.entity";
import { Booking } from "../modules/bookings/entities/booking.entity";
import { Customer } from "../modules/customers/entities/customer.entity";
@@ -20,7 +10,6 @@ import { ServiceType } from "../modules/rule-engine/entities/service-type.entity
import { Yard } from "../modules/rule-engine/entities/yard.entity";
import { WagonType } from "../modules/wagon-types/entities/wagon-type.entity";
import { ContainerType } from "../modules/rule-engine/entities/container-type.entity";
>>>>>>> bd6ad54eea229305a214d06081e0ffd27fe163b8
const SEED_FLAG = "SEED_DEMO_BOOKINGS";
@@ -220,11 +209,6 @@ export class DemoBookingsSeeder {
{ conflictPaths: { email: true } },
);
<<<<<<< HEAD
const [serviceType, company, yards, containerTypes] = await Promise.all([
manager.getRepository(ServiceType).findOneByOrFail({ code: SERVICE_TYPE_CODE }),
manager.getRepository(Customer).findOneByOrFail({ email: CUSTOMER_EMAIL }),
=======
const [serviceType, customer, yards, containerTypes] = await Promise.all([
manager
.getRepository(ServiceType)
@@ -232,7 +216,6 @@ export class DemoBookingsSeeder {
manager
.getRepository(Customer)
.findOneByOrFail({ email: CUSTOMER_EMAIL }),
>>>>>>> bd6ad54eea229305a214d06081e0ffd27fe163b8
manager.getRepository(Yard).find(),
manager.getRepository(ContainerType).find(),
]);
@@ -264,13 +247,8 @@ export class DemoBookingsSeeder {
await manager.getRepository(Booking).upsert(
{
reference: demoBooking.reference,
<<<<<<< HEAD
companyId: company.id,
status: 'APPROVED',
=======
companyId: customer.id,
status: "APPROVED",
>>>>>>> bd6ad54eea229305a214d06081e0ffd27fe163b8
scheduledDate: new Date(demoBooking.scheduledDate),
totalAmount: 0,
paymentStatus: "PENDING",

View File

@@ -16,6 +16,7 @@
"@edr/ui-common": "workspace:*",
"@tanstack/react-query": "^5.100.11",
"@tria-plc/iamui-common": "1.1.1",
"@hello-pangea/dnd": "^18.0.1",
"axios": "^1.7.7",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",

View File

@@ -0,0 +1 @@
export { Card, CardHeader, CardTitle, CardDescription, CardFooter, CardAction, CardContent } from '@edr/ui-common';

View File

@@ -1,42 +1,3 @@
<<<<<<< HEAD
import { useState } from 'react';
import { useTrains, useDeleteTrain, useCreateTrain } from '@/hooks/useTrains';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { useToast } from '@/hooks/use-toast';
import { Plus, Eye, Trash2 } from 'lucide-react';
import { Link } from 'react-router-dom';
const CreateTrainForm = ({ onSuccess }: { onSuccess: () => void }) => {
const [form, setForm] = useState({ code: '', capacityTons: 0, trainNumber: '', trainName: '' });
const createTrain = useCreateTrain();
const { toast } = useToast();
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
try {
await createTrain.mutateAsync(form);
toast({ title: 'Train created', description: `${form.code} added.` });
onSuccess();
} catch {
toast({ title: 'Error', description: 'Failed to create train.', variant: 'destructive' });
}
};
return (
<form onSubmit={handleSubmit} className="space-y-4">
<div><Label>Code*</Label><Input required value={form.code} onChange={e => setForm({...form, code: e.target.value})} /></div>
<div><Label>Capacity (tons)*</Label><Input type="number" required value={form.capacityTons} onChange={e => setForm({...form, capacityTons: parseFloat(e.target.value)})} /></div>
<div><Label>Train Number</Label><Input value={form.trainNumber} onChange={e => setForm({...form, trainNumber: e.target.value})} /></div>
<div><Label>Train Name</Label><Input value={form.trainName} onChange={e => setForm({...form, trainName: e.target.value})} /></div>
<Button type="submit" disabled={createTrain.isPending}>Save</Button>
</form>
=======
import { useMemo, useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { isAxiosError } from 'axios';
@@ -794,45 +755,7 @@ const TrainsPage = () => {
</DialogContent>
</Dialog>
</div>
>>>>>>> 523d7e58422f1bde8024c2dd237092a7cf6aa190
);
};
export default function TrainsPage() {
const { data: trains, isLoading } = useTrains();
const deleteTrain = useDeleteTrain();
const [open, setOpen] = useState(false);
if (isLoading) return <div className="p-8">Loading trains...</div>;
return (
<Card>
<CardHeader className="flex flex-row items-center justify-between">
<CardTitle>Trains</CardTitle>
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild><Button size="sm"><Plus className="mr-2 h-4 w-4" />New Train</Button></DialogTrigger>
<DialogContent><DialogHeader><DialogTitle>Create Train</DialogTitle></DialogHeader><CreateTrainForm onSuccess={() => setOpen(false)} /></DialogContent>
</Dialog>
</CardHeader>
<CardContent>
<Table>
<TableHeader><TableRow><TableHead>Number</TableHead><TableHead>Name</TableHead><TableHead>Status</TableHead><TableHead>Capacity</TableHead><TableHead>Actions</TableHead></TableRow></TableHeader>
<TableBody>
{trains?.map(train => (
<TableRow key={train.id}>
<TableCell>{train.trainNumber || train.code}</TableCell>
<TableCell>{train.trainName || '-'}</TableCell>
<TableCell><Badge variant="outline">{train.status}</Badge></TableCell>
<TableCell>{train.capacityTons} t</TableCell>
<TableCell className="flex space-x-2">
<Link to={`/trains/${train.id}`}><Button variant="ghost" size="icon"><Eye className="h-4 w-4" /></Button></Link>
<Button variant="ghost" size="icon" onClick={() => deleteTrain.mutate(train.id)}><Trash2 className="h-4 w-4" /></Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</CardContent>
</Card>
);
}
export default TrainsPage;

View File

@@ -1,5 +1,5 @@
import { apiClient } from '@/lib/axios';
//import { apiClient } from '@/lib/axios';
import { api as client } from "@/auth/http";
export interface Train {
id: string;
code: string;
@@ -17,10 +17,10 @@ export interface Train {
}
export const trainService = {
getAll: () => apiClient.get<Train[]>('/trains'),
getById: (id: string) => apiClient.get<Train>(`/trains/${id}`),
create: (data: Partial<Train>) => apiClient.post('/trains', data),
update: (id: string, data: Partial<Train>) => apiClient.patch(`/trains/${id}`, data),
delete: (id: string) => apiClient.delete(`/trains/${id}`),
getDetails: (id: string) => apiClient.get(`/trains/${id}/details`),
getAll: () => client.get<Train[]>('/trains'),
getById: (id: string) => client.get<Train>(`/trains/${id}`),
create: (data: Partial<Train>) => client.post('/trains', data),
update: (id: string, data: Partial<Train>) => client.patch(`/trains/${id}`, data),
delete: (id: string) => client.delete(`/trains/${id}`),
getDetails: (id: string) => client.get(`/trains/${id}/details`),
};

33
pnpm-lock.yaml generated
View File

@@ -184,6 +184,9 @@ importers:
'@edr/ui-common':
specifier: workspace:*
version: link:../../../packages/ui-common
'@hello-pangea/dnd':
specifier: ^18.0.1
version: 18.0.1(@types/react@18.3.29)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
'@tanstack/react-query':
specifier: ^5.100.11
version: 5.100.11(react@19.2.6)
@@ -1377,6 +1380,12 @@ packages:
'@gilbarbara/deep-equal@0.3.1':
resolution: {integrity: sha512-I7xWjLs2YSVMc5gGx1Z3ZG1lgFpITPndpi8Ku55GeEIKpACCPQNS/OTqQbxgTCfq0Ncvcc+CrFov96itVh6Qvw==}
'@hello-pangea/dnd@18.0.1':
resolution: {integrity: sha512-xojVWG8s/TGrKT1fC8K2tIWeejJYTAeJuj36zM//yEm/ZrnZUSFGS15BpO+jGZT1ybWvyXmeDJwPYb4dhWlbZQ==}
peerDependencies:
react: 19.2.6
react-dom: 19.2.6
'@hono/node-server@1.19.14':
resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==}
engines: {node: '>=18.14.1'}
@@ -5331,6 +5340,9 @@ packages:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'}
css-box-model@1.2.1:
resolution: {integrity: sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==}
css-line-break@2.1.0:
resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==}
@@ -8537,6 +8549,9 @@ packages:
'@types/react-dom':
optional: true
raf-schd@4.0.3:
resolution: {integrity: sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==}
raf@3.4.1:
resolution: {integrity: sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==}
@@ -11264,6 +11279,18 @@ snapshots:
'@gilbarbara/deep-equal@0.3.1': {}
'@hello-pangea/dnd@18.0.1(@types/react@18.3.29)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)':
dependencies:
'@babel/runtime': 7.29.2
css-box-model: 1.2.1
raf-schd: 4.0.3
react: 19.2.6
react-dom: 19.2.6(react@19.2.6)
react-redux: 9.3.0(@types/react@18.3.29)(react@19.2.6)(redux@5.0.1)
redux: 5.0.1
transitivePeerDependencies:
- '@types/react'
'@hono/node-server@1.19.14(hono@4.12.22)':
dependencies:
hono: 4.12.22
@@ -16070,6 +16097,10 @@ snapshots:
shebang-command: 2.0.0
which: 2.0.2
css-box-model@1.2.1:
dependencies:
tiny-invariant: 1.3.3
css-line-break@2.1.0:
dependencies:
utrie: 1.0.2
@@ -19735,6 +19766,8 @@ snapshots:
'@types/react': 18.3.29
'@types/react-dom': 18.3.7(@types/react@18.3.29)
raf-schd@4.0.3: {}
raf@3.4.1:
dependencies:
performance-now: 2.1.0