Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UpsertGraph not inserting into join table #2544

Open
moe8622 opened this issue Oct 18, 2023 · 0 comments
Open

UpsertGraph not inserting into join table #2544

moe8622 opened this issue Oct 18, 2023 · 0 comments

Comments

@moe8622
Copy link

moe8622 commented Oct 18, 2023

Hey folks!
I am trying to use upsertGraph to insert a row into my order table while creating a new order_item row and relating it to the order and also relating that order to an already existing product and requestor. The order_item table basically acts as a join table between the order and the product but has extra properties. The relates for product and requestor work just fine but the upsert does not create a new row in the order_item table for some reason. Here are the details:

Objection version: ^3.1.2

Base model Class:

export class BaseModel extends softDelete(Model) {
    public id?: number;
    public created_on?: string;
    public created_by?: number;
    public changed_on?: string;
    public changed_by?: number;
    public is_deleted?: boolean;

    constructor({
    	id,
    	created_on,
    	created_by,
    	changed_on,
    	changed_by,
    	is_deleted
    }: {
        id?: number,
        created_on?: string,
        created_by?: number,
        changed_on?: string,
        changed_by?: number,
        is_deleted?: boolean,
    } = {}) {
    	super();
    	this.id = id;
    	this.created_on = created_on;
    	this.created_by = created_by;
    	this.changed_on = changed_on;
    	this.changed_by = changed_by;
    	this.is_deleted = is_deleted;
    }

    async $beforeUpdate(opt: ModelOptions, queryContext: QueryContext): Promise<any> {
    	await super.$beforeUpdate(opt, queryContext);
    	this.changed_on = new Date().toISOString();
    }

    async $beforeInsert(queryContext: QueryContext): Promise<any> {
    	await super.$beforeInsert(queryContext);
    	this.created_on = new Date().toISOString();
    }

    static get baseProperties() {
    	return {
    		id:         { type: 'integer' },
    		created_on: { type: 'string' },
    		created_by: { type: 'integer' },
    		changed_on: { type: 'string' },
    		changed_by: { type: 'integer' },
    		is_deleted: { type: 'boolean' }
    	};
    }
}

Order Class:

export class Order extends BaseModel {
        public product_id?: number;
        public requestor_id?: number;

        static get jsonSchema() {
    	        return {
    		        type: 'object',
    		        required: [],
        
    		        properties: {
    			        ...this.baseProperties,
    			        product_id:                 { type: 'integer' },
    			        requestor_id:               { type: 'integer' },
    		        }
    	        };
        }

	static get relationMappings() {
    	return {
    		requestor: {
    			relation: BaseModel.BelongsToOneRelation,
    			modelClass: User,
    			join: {
    				from: 'order.requestor_id',
    				to: 'usr.id'
    			}
    		},
	        items: {
		        relation: BaseModel.HasManyRelation,
		        modelClass: OrderItem,
		        join: {
			        from: 'order.id',
			        to: 'order_item.order_id'
		        }
	        },
    		product: {
    			relation: BaseModel.BelongsToOneRelation,
    			modelClass: Product,
    			join: {
    				from: 'order.product_id',
    				to: 'product.id'
    			}
    		}
        }
}

Order Item Class:

export class OrderItem extends BaseModel {
    public order_id?: number;
    public product_id?: number;
    public date_produced?: string;
    public date_shipped?: string;
    public date_received?: string;
    public quantity?: number;
    public design_hrs?: number;
    public print_hrs?: number;
    public labour_hrs?: number;
    public is_sample?: boolean;

    constructor({
    	order_id,
    	product_id,
    	date_produced,
    	date_shipped,
    	date_received,
    	quantity,
    	design_hrs,
    	print_hrs,
    	labour_hrs,
    	is_sample
    }: {
        order_id?: number,
        product_id?: number,
        date_produced?: string,
        date_shipped?: string,
        date_received?: string,
        quantity?: number,
        design_hrs?: number,
        print_hrs?: number,
        labour_hrs?: number,
        is_sample?: boolean
    } = {}) {
    	super();
    	this.order_id = order_id;
    	this.product_id = product_id;
    	this.date_produced = date_produced;
    	this.date_shipped = date_shipped;
    	this.date_received = date_received;
    	this.quantity = quantity;
    	this.design_hrs = design_hrs;
    	this.print_hrs = print_hrs;
    	this.labour_hrs = labour_hrs;
    	this.is_sample = is_sample;
    }

    static get tableName() {
    	return 'order_item';
    }

    static get idColumn() {
    	return ['order_id', 'product_id'];
    }

    static get jsonSchema() {
    	return {
    		type: 'object',
    		required: [],

    		properties: {
    			order_id:      { type: 'integer' },
    			product_id:    { type: 'integer' },
    			date_produced: { type: 'string', nullable: true },
    			date_shipped:  { type: 'string', nullable: true },
    			date_received: { type: 'string', nullable: true },
    			quantity:      { type: 'number' },
    			design_hrs:    { type: 'number' },
    			print_hrs:     { type: 'number' },
    			labour_hrs:    { type: 'number' },
    			is_sample:     { type: 'boolean' }
    		}
    	};
    }
    
    static get relationMappings() {
    	return {
    		products: {
    			relation: BaseModel.HasManyRelation,
    			modelClass: Product,
    			join: {
    				from: 'order_item.product_id',
    				to: 'product.id'
    			}
    		},
    		orders: {
    			relation: BaseModel.HasManyRelation,
    			modelClass: Order,
    			join: {
    				from: 'order_item.order_id',
    				to: 'order.id'
    			}
    		},
         }
    }
}

Order Table DDL:

CREATE TABLE "order" (
	id serial4 NOT NULL,
	product_id int4 NOT NULL,
	requestor_id int4 NOT NULL,
	created_on timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
	created_by int4 NULL DEFAULT 1,
	changed_on timestamptz NULL DEFAULT CURRENT_TIMESTAMP,
	changed_by int4 NULL,
	is_dummy bool NULL DEFAULT false,
	CONSTRAINT order_pk PRIMARY KEY (id)
);

ALTER TABLE "order" ADD CONSTRAINT ordr_prd_fk FOREIGN KEY (product_id) REFERENCES product(id);
ALTER TABLE "order" ADD CONSTRAINT ordr_rqstr_fk FOREIGN KEY (requestor_id) REFERENCES usr(id);

Order Item Table DDL:

CREATE TABLE order_item (
	order_id int4 NOT NULL,
	product_id int4 NOT NULL,
	date_produced timestamptz NULL,
	date_shipped timestamptz NULL,
	date_received timestamptz NULL,
	quantity int4 NULL,
	design_hrs float4 NULL,
	print_hrs float4 NULL,
	labour_hrs float4 NULL,
	is_sample bool NULL DEFAULT false,
	created_on timestamptz NULL DEFAULT CURRENT_TIMESTAMP,
	changed_on timestamptz NULL,
	CONSTRAINT order_item_pk PRIMARY KEY (order_id, product_id)
);

ALTER TABLE order_item ADD CONSTRAINT order_item_order_id_foreign FOREIGN KEY (order_id) REFERENCES order(id);
ALTER TABLE order_item ADD CONSTRAINT order_item_product_id_foreign FOREIGN KEY (product_id) REFERENCES product(id);

Query:

async function createOrder() {
		const dummy_order = {
			product: { id: 3496 },
			requestor: { id: 2654 },
			items: [{
				product_id: 3464
			}]
		};

		return await transaction(
			Order,
			async (
				Order
			) => {
				const inserted_order = await Order
					.query()
					.upsertGraphAndFetch(dummy_order, {
						relate: true,
						allowRefs: true,
						insertMissing: true,
						noUpdate: ['items.materials', 'product'],
						noInsert: ['product']
					})
					.catch((err: any) => {
						console.log('Error creating order', err);
						errorReporting().report(err);
						throw new Error(err);
					});

				console.log(inserted_order);
				return inserted_order;
			}
		);
}

The logs for inserted_order shows an empty array for items among other fetched values: { ..., items: [], ...}. There are no error messages and the order gets created successfully. Just the order_item does not. Could someone please tell me what I'm doing wrong?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant