Vue js and Laravel problem with computed properties can't save data in database - laravel

Iam beginner in vue js and i need help.I'm working on invoice application and i want when select customer to auto fill data properties and i'm using computed properties to get data which i need.
I succeed to save only once in database and then it gives me error in laravelI see in vue devtool that computed properties remain the same like first time and they don't change except when i click on component in vuetools and they will be saved again.This is my data form:
form: {
customer_id: null,
project_id: null,
invoice_date: this.invoice_data.invoice_date,
due_date: null,
invoice_number: this.invoice_data.invoice_number,
item_id: null,
billing_address: null,
billing_city: null,
billing_state: null,
billing_zip_code: null,
billing_country_id : null,
shipping_country_id: null,
shipping_address: null,
shipping_city: null,
shipping_state: null,
shipping_zip_code: null,
items_test: null,
},
This is my computed property how i find data when i select customer:
customer_object: function() {
return this.customers.find(customer => customer.id === this.form.customer_id) ?? ""
},
These are my props:
props: {
customers: Object,
users: Object,
countries: Object,
currencies:Object,
items:Object,
payment_modes: Object,
invoice_data: Object,
// invoice_items:Object,
products:Object,
// projects:Object,
// customers_projects: Object,
// filters: Object,
// groups: Object,
errors: Object,
},
This is another computed how i try to put values in form when i select customer:
formCount: function () {
return [
this.form.billing_address = this.customer_object.address,
this.form.billing_city = this.customer_object.city,
this.form.billing_state = this.customer_object.state,
this.form.billing_zip_code = this.customer_object.zip_code,
this.form.billing_country_id = this.customer_object.country_id,
this.form.shipping_city = this.customer_object.shipping_city,
this.form.shipping_state = this.customer_object.shipping_state,
this.form.shipping_address = this.customer_object.shipping_address,
this.form.shipping_zip_code = this.customer_object.shipping_zip_code,
this.form.shipping_country_id = this.customer_object.shipping_country_id,
]
},

Related

keystonejs form a multi-column unique constraint

How to form a unique constraint with multiple fields in keystonejs?
const Redemption = list({
access: allowAll,
fields: {
program: relationship({ ref: 'Program', many: false }),
type: text({ label: 'Type', validation: { isRequired: true }, isIndexed: 'unique' }),
name: text({ label: 'name', validation: { isRequired: true }, isIndexed: 'unique' }),
},
//TODO: validation to check that program, type, name form a unique constraint
})
The best way I can think to do this currently is by adding another field to the list and concatenating your other values into it using a hook. This lets you enforces uniqueness across these three values (combine) at the DB-level.
The list config (and hook) might look like this:
const Redemption = list({
access: allowAll,
fields: {
program: relationship({ ref: 'Program', many: false }),
type: text({ validation: { isRequired: true } }),
name: text({ validation: { isRequired: true } }),
compoundKey: text({
isIndexed: 'unique',
ui: {
createView: { fieldMode: 'hidden' },
itemView: { fieldMode: 'read' },
listView: { fieldMode: 'hidden' },
},
graphql: { omit: ['create', 'update'] },
}),
},
hooks: {
resolveInput: async ({ item, resolvedData }) => {
const program = resolvedData.program?.connect.id || ( item ? item?.programId : 'none');
const type = resolvedData.type || item?.type;
const name = resolvedData.name || item?.name;
resolvedData.compoundKey = `${program}-${type}-${name}`;
return resolvedData;
},
}
});
Few things to note here:
I've removed the isIndexed: 'unique' config for the main three fields. If I understand the problem you're trying to solve correctly, you actually don't want these values (on their own) to be distinct.
I've also remove the label config from your example. The label defaults to the field key so, in your example, that config is redundant.
As you can see, I've added the compoundKey field to store our composite values:
The ui settings make the field appear as uneditable in the UI
The graphql settings block updates on the API too (you could do the same thing with access control but I think just omitting the field is a bit cleaner)
And of course the unique index, which will be enforced by the DB
I've used a resolveInput hook as it lets you modify data before it's saved. To account for both create and update operations we need to consult both the resolvedData and item arguments - resolvedData gives us new/updated values (but undefined for any fields not being updated) and item give us the existing values in the DB. By combining values from both we can build the correct compound key each time and add it to the returned object.
And it works! When creating a redemption we'll be prompted for the 3 main fields (the compound key is hidden):
And the compound key is correctly set from the values entered:
Editing any of the values also updates the compound key:
Note that the compound key field is read-only for clarity.
And if we check the resultant DB structure, we can see our unique constraint being enforced:
CREATE TABLE "Redemption" (
id text PRIMARY KEY,
program text REFERENCES "Program"(id) ON DELETE SET NULL ON UPDATE CASCADE,
type text NOT NULL DEFAULT ''::text,
name text NOT NULL DEFAULT ''::text,
"compoundKey" text NOT NULL DEFAULT ''::text
);
CREATE UNIQUE INDEX "Redemption_pkey" ON "Redemption"(id text_ops);
CREATE INDEX "Redemption_program_idx" ON "Redemption"(program text_ops);
CREATE UNIQUE INDEX "Redemption_compoundKey_key" ON "Redemption"("compoundKey" text_ops);
Attempting to violate the constraint will produce an error:
If you wanted to customise this behaviour you could implement a validateInput hook and return a custom ValidationFailureError message.

How can I specify a Yup error on a validating field's parent schema?

I'm trying to set up a validation schema to use with Formik. I have a combobox that has items of shape { id: number; value: string; } and pulls the value out to display to the user, while submitting the whole item to Formik/Yup. However, in production, I won't know the shape of my items ahead of time; this is just the shape I've chosen for demoing.
const items = [
{ id: 1, value: 'foo' },
{ id: 2, value: 'bar' },
];
const [ field, meta, helpers ] = useField('value');
return (
<ComboBox
{...field}
invalid={meta.touched && !!meta.errors}
invalidText={meta.errors}
items={items}
itemToString={i => i?.value ?? ''}
onChange={data => helpers.setValue(data.selectedItem)}
selectedItem={field.value}
/>
);
I want to make only id = 1 to be valid.
const validationSchema = Yup.object({
value: Yup.object({
id: Yup.number().oneOf([1], "You've selected an invalid option."),
value: Yup.string(),
})
.required('You have not selected an option.')
.nullable(),
});
However, when this is in the error state, meta.errors is set to { id: "You've selected an invalid option." }. invalidText expects a ReactChild so when it receives this object, React throws an error.
I assume the solution, then, is to move .oneOf() to outside of the inner Yup.object(). I don't know how to specify the valid values, however, and neither the documentation nor a quick search of SO helped. Thoughts?

Create complex argument-driven queries from AWS Lambda?

Look for // HERE IS THE PROBLEM PART sentence to find code that is the problem.
I am trying to implement AppSync using AWS Lambda (that connects to RDS Postgres server) as a data source. I want to create puKnowledgeFile query that will update my KnowledgeFile with optional arguments. If the client only provided htmlText and properties as arguments, then my update query should only update these two fields.
type Mutation {
putKnowledgeFile(
id: ID!,
htmlText: String,
plainText: String,
properties: AWSJSON
): KnowledgeFile
}
type KnowledgeFile {
id: ID!
htmlText: String!
plainText: String!
properties: AWSJSON!
lastDateTimeModified: AWSDateTime!
dateTimeCreated: AWSDateTime!
}
Here is an piece of AWS Lambda code:
exports.handler = async (event, context, callback) => {
/* Connecting to Postgres */
let data = null;
let query = ``;
let values = [];
switch (event.info.fieldName) {
case "putKnowledgeFile":
if(event.arguments.htmlText === undefined &&
event.arguments.plainText === undefined &&
event.arguments.properties === undefined) {
callback(`At least one argument except id should be provided in putKnowledgeFile request`);
}
// HERE IS THE PROBLEM PART
query += `update knowledge_file`
query += `
set `;
let index = 0;
for (let fieldName in event.arguments) {
if(arguments.hasOwnProperty(fieldName)) {
const fieldValue = event.arguments[fieldName];
if(index === 0) {
query += `${fieldName}=$${index+1}`
values.push(fieldValue);
} else {
query += `, ${fieldName}=$${index+1}`
values.push(fieldValue);
}
index++;
}
}
query += `
where knowledge_file.id = $${index+1};`;
values.push(event.arguments.id);
// HERE IS THE PROBLEM PART
break;
default:
callback(`There is no functionality to process this field: ${event.info.fieldName}`);
return;
}
let res = null;
try {
res = await client.query(query, values); // just sending created query
} catch(error) {
console.log("#client.query");
console.log(error);
}
/* DisConnecting from Postgres */
callback(null, res.rows);
};
Basically, this algorithm creates my query string through multiple string concatenations. I think it's too complicated and error-prone. Is there a way to create dynamic queries based on the presence / absence of certain arguments easily?
Just in case, here is my PostgreSQL schema:
-- main client object for clients
CREATE TABLE client (
id bigserial primary key,
full_name varchar(255)
);
-- knowledge_file
create table knowledge_file (
id bigserial primary key,
html_text text,
plain_text text,
properties jsonb,
last_date_modified timestamptz,
date_created timestamptz,
word_count varchar(50)
);
-- which client holds which knowledge file
create TABLE client_knowledge_file (
id bigserial primary key,
client_id bigint not null references client(id),
knowledge_file_id bigint not null references knowledge_file(id) unique ON DELETE CASCADE
);
I know this is not an optimum solution and might not completely answer your question but I also ran into similar problem and this is how I solved it.
I created a resolver pipeline.
In one function, I used the select statement to get the current
record.
In second function, I checked if the fields (in your case htmlText and properties) are null. If true, then use the ctx.prev.result values otherwise use the new ones).
Practical example
First resolver function:
{
"version": "2018-05-29",
"statements": [
"select id, html_text AS \"htmlText\", plain_text AS \"plainText\", properties, last_date_modified AS \"lastDateTimeModified\", date_created AS \"dateTimeCreated\" from knowledge_file where id = $ctx.args.Id"
]
}
Second resolver function:
#set($htmlText = $util.defaultIfNull($ctx.args.htmlText , $ctx.prev.result.htmlText))
#set($properties = $util.defaultIfNull($ctx.args.properties , $ctx.prev.result.properties))
{
"version": "2018-05-29",
"statements": [
"update knowledge_file set html_text = $htmlText, plain_text = $ctx.args.plainText, properties = $properties, last_date_modified = CURRENT_TIMESTAMP, date_created = CURRENT_DATE where id = $ctx.args.Id returning id, html_text AS \"htmlText\", plain_text AS \"plainText\", properties, last_date_modified AS \"lastDateTimeModified\", date_created AS \"dateTimeCreated\""
]
}

How Laravel Append Two Object result to one Collection Object

I want to con-cat two query result to one collection and pass to Laravel Resource file.
What I Did:
There is a Function called: getDailyUsageByPeriod($dateFrom, $dateTo, $serviceId), This is return an array of daily usage for a given period.
There is a function called: getTotalUsageByPeriod($dateFrom, $dateTo, $serviceId), This is return total for the given time period.
Ex- if user gave one week date range to $dateFrom and $dateTo variable first function return daily usage and second function return total usage for one week.
Then I return this result to Resource file. In the resource file
$dailyUsage = $this->getDailyUsageByPeriod($dateFrom, $dateTo, $resultForServiceNumber->id);
$totalUsage = $this->getTotalUsageByPeriod($dateFrom, $dateTo, $resultForServiceNumber->id);
$dailyUsage->total = $totalUsage;
How Return as a One collection object to resource file, because currently I am getting total record repeats.
`{
"date": "2019-06-01",
"peakPeriod": {
"upload": "496047",
"download": "496047"
},
"offpeakPeriod": {
"upload": "22233301",
"download": "12312332"
},
"totalUsage": {
"peakUpload": null,
"peakDownload": null,
"offpeakUpload": null,
"offpeakDownload": null
}
},
{
"date": "2019-05-01",
"peakPeriod": {
"upload": "12312343",
"download": "37044092"
},
"offpeakPeriod": {
"upload": "22233301",
"download": "12312332"
},
"totalUsage": {
"peakUpload": null,
"peakDownload": null,
"offpeakUpload": null,
"offpeakDownload": null
}
}`

Issue with enum data type in create function

I have created "blogs" table with id(primary key), title ,created at ,updated at , status (with enum type having values "active,inactive,hidden" with default value "active")
create function on Blog Model is working fine when giving status value from above mentioned set of values and empty value
const Blog = sequelize.define('blog', { id: { type:
Sequelize.INTEGER,
primaryKey: true, autoIncrement: true }, text: Sequelize.STRING,
status : { type : Sequelize.ENUM, allowNull : false, values :
['Inactive','Active','Hidden'], defaultValue : 'Active' } });
Blog.create({"title" :"hello","status":"abc"}).then(result => {
console.log(result);
});
The above code inserted a new record in blogs table with status of empty value.but result object having status of "abc".How can I get newly inserted record ?
You should define ENUM like this:
status : {
type : Sequelize.ENUM('Inactive','Active','Hidden'),
allowNull : false,
defaultValue : 'Active',
validate: {
isIn: {
args: [['Inactive','Active','Hidden']],
msg: "Wrong status"
}
}
}
In order to validate enum values you can use per attribute validation

Resources