I have the following models:
type Field #model {
id: ID!
fieldID: ID #index(name: "byField", sortKeyFields: ["name"])
name: String!
type: String!
required: Boolean
fields: [Field] #hasMany(indexName: "byField", fields: ["id"])
}
type Mutation {
batchCreateField(fields: [BatchCreateField]): [Field]
}
input BatchCreateField {
id: ID
fieldID: ID
name: String!
type: String!
required: Boolean
fields: [BatchCreateField]
}
And wrote a custom resolver:
$util.log.info($util.toJson($context))
#set($isAuthorized = false)
#set( $createdAt = $util.time.nowISO8601() )
#set($fieldsArray = [])
#foreach($item in \${ctx.args.fields})
$util.qr($item.put("id", $util.defaultIfNullOrBlank($item.id, $util.autoId())))
$util.qr($item.put("createdAt", $util.defaultIfNull($item.createdAt, $createdAt)))
$util.qr($item.put("updatedAt", $util.defaultIfNull($item.updatedAt, $createdAt)))
$util.qr($item.put("__typename", "Field"))
$util.qr($fieldsArray.add($util.dynamodb.toMapValues($item)))
#end
## [End] Initialization default values. **
$util.toJson( {
"version": "2018-05-29",
"operation": "BatchPutItem",
"tables": {
"Field-INSERT_APIID-INSERT_PROJECT_ENV": $fieldsArray
}
} )
Saving in batch works fine, the self relation is not working. Is there any way i can save this self relation like below in a batch and the resolver autofilling the sub fields with the fieldID of the previously inserted field?
let fieldInput: CreateFieldInput = {
name: field.name,
type: field.type,
required: field.required,
fields: field.fields
};
batchFieldsInput.push(fieldInput)
API.graphql(graphqlOperation(batchCreateField, {fields: batchFieldsInput}))
I use postman and i create API with the openAPI 3.0.
Problem is when i send this request, if i add body or not it return status code 200. I don't understand because i said i my code required for requestbody and for field in this body but nothing worth (without body code 200 and without GRP_CNOM code 200)...
SomeOne can help me ?
my openAPI code :
post:
operationId: CreationGroup
summary: Creation groupe
requestBody:
$ref: '#/components/requestBodies/crea'
responses:
'200':
description: '200 - Création du groupe effectué'
content:
application/json:
schema:
type: object
properties:
code:
type: integer
message:
type: string
example:
code: 200
message: Le groupe a bien été créé
'400':
description: '400 - Création du groupe échouée'
content:
application/json:
schema:
type: object
properties:
code:
type: integer
message:
type: string
example:
code: 200
message: Le groupe a échouée
'401':
$ref: '#/components/responses/UnauthorizedError'
default:
description: 'Erreur'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
requestBodies:
crea:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Group'
example:
$ref: '#/components/examples/oneGroupOrga'
securitySchemes:
jwtAuth:
type: http
scheme: bearer
bearerFormat: JWT
examples:
oneGroupOrga:
value:
GRP_CNOM: Princ
GRP_SPKGROUPE: 2
GRP_SFKINSTANCE: 1
GRP_CBORDERCOLOR: "#F5370E"
GRP_BSOCIETE: true
GRP_BETABLISSEMENT: true
GRP_BUNITE: false
GRP_CSIRET: null
GRP_SFKAPE: 1
GRP_CCAPITAL: "200000"
GRP_SMOISDEBUTEXERCICECOMPTABLE: 1
GRP_CABREVIATIONSOCIETE: PR
GRP_CNUMEROTVAINTRACOMMUNAUTAIRE: ""
GRP_DCOEFFICIENTENCOURSCOMPTABLE: 70
GRP_CADRESSE: 113 boulevard de Lamasquère
GRP_CCODEPOSTAL: "31600"
GRP_SFKVILLE: 1
GRP_SFKPAYS: 1
GRP_CENTETETEXTE: "PRINC"
GRP_CENTETEIMAGE: "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"
GRP_CPIEDDEPAGEIMAGE: "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"
GRP_CPIEDDEPAGETEXTE: "113 boulevard de Lamasquère - 31600 MURET - 890720824"
GRP_SFKFONCTION: 1
GRP_DNOTATION: null
GRP_CCOMMENTAIRE: null
GRP_SFKFORMBUILDER: 1
GRP_CSIREN: "890 720 824"
GEG_SFKGROUPEPARENT120: 1
GRP_SFKGROUPETYPE: 650
ADM_COMPTEBANCAIRE:
-
CBC_SPKCOMPTE: 1
CBC_CNOMDUCOMPTE: Compte courant
CBC_CNOMDELABANQUE: CIC
CBC_CDOMICILIATION: ""
CBC_CBIC: ""
CBC_CRIB: ""
CBC_CIBAN: ""
CBC_BPARDEFAUT: true
ADM_UTILISATEUR_GROUPE:
-
UGR_SFKUTILISATEUR: 1
UGR_SFKFONCTION: 2
schemas:
Group:
type: object
discriminator:
propertyName: GRP_CNOM
required:
-
GRP_CNOM
properties:
GRP_CNOM:
type: string
GRP_SPKGROUPE:
type: integer
GRP_SFKINSTANCE:
type: integer
GRP_SFKROLE:
type: integer
nullable: true
GRP_CBORDERCOLOR:
type: string
nullable: true
GRP_BSOCIETE:
type: boolean
GRP_BETABLISSEMENT:
type: boolean
GRP_BUNITE:
type: boolean
GRP_CSIRET:
type: string
nullable: true
GRP_SFKAPE:
type: integer
nullable: true
GRP_CCAPITAL:
type: string
nullable: true
GRP_SMOISDEBUTEXERCICECOMPTABLE:
type: integer
nullable: true
GRP_CABREVIATIONSOCIETE:
type: string
nullable: true
GRP_CNUMEROTVAINTRACOMMUNAUTAIRE:
type: string
nullable: true
GRP_DCOEFFICIENTENCOURSCOMPTABLE:
type: number
nullable: true
GRP_CADRESSE:
type: string
nullable: true
GRP_CCODEPOSTAL:
type: string
nullable: true
GRP_SFKVILLE:
type: integer
nullable: true
GRP_SFKPAYS:
type: integer
nullable: true
GRP_CENTETETEXTE:
type: string
nullable: true
GRP_CENTETEIMAGE:
type: string
format: byte
nullable: true
GRP_CPIEDDEPAGEIMAGE:
type: string
format: byte
nullable: true
GRP_CPIEDDEPAGETEXTE:
type: string
nullable: true
GRP_SFKFONCTION:
type: integer
nullable: true
GRP_DNOTATION:
type: number
nullable: true
GRP_CCOMMENTAIRE:
type: string
nullable: true
GRP_SFKFORMBUILDER:
type: integer
nullable: true
GRP_CSIREN:
type: string
nullable: true
GEG_SFKGROUPEPARENT120:
type: integer
nullable: true
GRP_SFKGROUPETYPE:
type: integer
enum:
-
650
-
651
-
652
GEG_SFKGROUPEENFANT122:
type: array
items:
type: string
GEG_SFKGROUPEENFANT121:
type: array
items:
type: object
properties:
GRP_SPKGROUPE:
type: integer
GRP_SFKGROUPETYPE:
type: integer
enum:
-
650
-
651
-
652
required:
-
GRP_SPKGROUPE
-
GRP_SFKGROUPETYPE
ADM_COMPTEBANCAIRE:
type: array
items:
type: object
properties:
CBC_SPKCOMPTE:
type: integer
CBC_CNOMDUCOMPTE:
type: string
CBC_CNOMDELABANQUE:
type: string
CBC_CDOMICILIATION:
type: string
CBC_CBIC:
type: string
CBC_CRIB:
type: string
CBC_CIBAN:
type: string
CBC_BPARDEFAUT:
type: boolean
default: false
required:
-
CBC_CNOMDUCOMPTE
ADM_UTILISATEUR_GROUPE:
type: array
items:
type: object
properties:
UGR_SFKUTILISATEUR:
type: integer
UGR_SFKFONCTION:
type: integer
UGR_SFKDROIT:
type: integer
enum:
-
59
-
60
required:
-
UGR_SFKUTILISATEUR
Error:
type: object
properties:
code:
type: integer
format: int32
message:
type: string
responses:
UnauthorizedError:
description: Le token est invalid ou manquant
security:
-
jwtAuth: [] ```
You can place the required in the paths instead of the components. For example:
[...]
post:
operationId: CreationGroup
summary: Creation groupe
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/requestBodies/crea'
responses:
[...]
If required would be in components then it would be required every time its used. However, in reality, whether a request body is required depends on the route. That is why they like you to put it in the paths section.
I'm using Sequelize.js with SQLite-database and faced a question with setting a value for foreign key. I have the following code:
const MessageModel = sequelize.define('MessageModel ', {
uuid: DataTypes.STRING,
authorId: DataTypes.STRING,
// ... other props
}, {});
const TodoModel = sequelize.define('TodoModel', {
ownerId: DataTypes.STRING,
status: {
type: DataTypes.STRING,
defaultValue: 'pending'
}
}, {});
TodoModel.belongsTo(MessageModel , {
foreignKey: {
name: 'messageId',
field: 'messageId',
allowNull: false
},
targetKey: 'uuid'
});
MessageModel.create({
uuid: 'testUUIDForExample'
// other props
}).then(message => {
console.log(`Message's created successful`);
TodoModel.create({
ownerId: 'id-string',
status: 'test-status',
messageId: 'testUUIDForExample'
})
})
Sequelize creates MessageModel-row in DB, but it falls when it's trying to generate TodoModel with this err:
DatabaseError: SQLITE_ERROR: foreign key mismatch - "TodoModel" referencing "MessageModel "
at Query.formatError (C:\Users\lrsvo\web-development\projects\platoon-web-electron\node_modules\sequelize\lib\dialects\sqlite\query.js:432:16)
at Query._handleQueryResponse (C:\Users\lrsvo\web-development\projects\platoon-web-electron\node_modules\sequelize\lib\dialects\sqlite\query.js:77:18)
at afterExecute (C:\Users\lrsvo\web-development\projects\platoon-web-electron\node_modules\sequelize\lib\dialects\sqlite\query.js:260:31)
at Statement.errBack (C:\Users\lrsvo\web-development\projects\platoon-web-electron\node_modules\sqlite3\lib\sqlite3.js:16:21)
Err.original.message: "SQLITE_ERROR: foreign key mismatch - "TodoModel" referencing "MessageModel"
Generated SQL:
"INSERT INTO `TodoModel` (`id`,`ownerId`,`status`,`createdAt`,`updatedAt`,`messageId`) VALUES (NULL,$1,$2,$3,$4,$5);"
My TodoModel table looks like:
CREATE TABLE "TodoModel" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
"ownerId" VARCHAR(255),
"status" TEXT DEFAULT 'pending',
"createdAt" DATETIME NOT NULL,
"updatedAt" DATETIME NOT NULL,
"messageId" VARCHAR(255) NOT NULL,
FOREIGN KEY("messageId") REFERENCES "MessageModel"("uuid") ON DELETE NO ACTION ON UPDATE CASCADE
);
I can't get why is the err occurs and need help, cause I'm dummy in this ORM.
I'm using "sequelize": "^5.1.0" with SQLite.
MyConfig file:
const Sequelize = require("sequelize");
const electron = require('electron');
const storagePath = electron.app.getPath('userData') + '/plt.db';
module.exports = {
development: {
dialect: "sqlite",
storage: storagePath,
username: null,
password: null,
operatorsAliases: Sequelize.Op,
define: { freezeTableName: true },
query: { raw: true }, // Always get raw result
logging: true,
},
};
There are a copuple of things here. First If you are going to use uuid on MessageModel as primary key, you have to define it, otherwise you'll have a default id field.
const MessageModel = sequelize.define('MessageModel ', {
uuid:{ // if this is your primary key you have to define it
type: DataTypes.STRING, //there is also DataTypes.UUID
allowNull: false,
primaryKey: true,
unique: true
},
authorId: DataTypes.STRING,
// ... other props
}, {});
Then on your TodoModel, you are setting the messageId association as integer. To change it to string, you have to define the field on the model, and on the association use it as a foreign key.
const TodoModel = sequelize.define('TodoModel', {
ownerId: DataTypes.STRING,
status: {
type: DataTypes.STRING,
defaultValue: 'pending'
},
messageId: { //you also have to add the field on your model and set it as STRING, because on the association Sequelize by default is going to use INTEGER
type: DataTypes.STRING,
allowNull: false
}
}, {});
TodoModel.belongsTo(MessageModel , {
as: 'Message',
foreignKey: 'messageId', // and you only set the foreignKey - Same name as your field above
});
I have Entities with One-to-Many relationship
TransactionItem -- has many --> Payments
EDIT: included the mapping files
Payment.yml mapping file
Akademia\Institution\Sales\Domain\Model\Payment\Payment:
type: entity
table: payments
repositoryClass: Akademia\Institution\Sales\Infrastructure\Persistence\Doctrine\Payment\DoctrinePaymentRepository
id:
id:
type: string
length: 36
fields:
date:
type: datetime
amount:
type: decimal
precision: 11
scale: 2
manyToOne:
transactionItem:
targetEntity: Akademia\Institution\Sales\Domain\Model\TransactionItem
inversedBy: payments
joinColumn:
name: transaction_item_id
referencedColumnName: id
TransactionItem.yml mapping
Akademia\Institution\Sales\Domain\Model\TransactionItem:
type: entity
table: transaction_items
repositoryClass: Akademia\Institution\Sales\Infrastructure\Persistence\Doctrine\DoctrineTransactionItemRepository
id:
id:
type: string
length: 36
fields:
productId:
type: string
column: product_id
productType:
type: string
column: product_type
description:
type: string
quantity:
type: integer
price:
type: decimal
precision: 11
scale: 2
discount:
type: decimal
precision: 11
scale: 2
paid:
type: boolean
remarks:
type: string
nullable: true
manyToOne:
transaction:
targetEntity: Akademia\Institution\Sales\Domain\Model\Transaction
inversedBy: lineItems
joinColumn:
name: transaction_id
referencedColumnName: id
oneToMany:
payments:
targetEntity: Akademia\Institution\Sales\Domain\Model\Payment\Payment
mappedBy: transactionItem
cascade: ['persist']
fetch: EAGER
when Im calling
$transactionItem->pay($amount, $date);
$entityManager->persist($transactionItem);
$entityManager->flush();
TransactionItem.php
public function pay($amount, \DateTime $date = null)
{
$payment = new Payment(
Uuid::uuid4()->toString(),
$this,
$amount,
$date ?? new \DateTime());
$this->payments[] = $payment;
}
Im expecting that I can get the TransactionItem on doctrine callbacks here:
services.yml
services:
app.doctrine_event_listener:
class: AppBundle\Event\DomainEventListener
arguments: ["#app.domain_event_dispatcher"]
tags:
- { name: doctrine.event_listener, event: postPersist }
- { name: doctrine.event_listener, event: postUpdate }
- { name: doctrine.event_listener, event: postRemove }
- { name: doctrine.event_listener, event: postFlush }
app.domain_event_dispatcher:
class: AppBundle\Event\DefaultEventDispatcher
The listener:
class DomainEventListener
{
private $entities = array();
/** #var DomainEventDispatcher */
private $dispatcher;
public function __construct(DomainEventDispatcher $dispatcher)
{
$this->dispatcher = $dispatcher;
}
public function postPersist($event)
{
$this->keepAggregateRoots($event);
}
public function postUpdate($event)
{
$this->keepAggregateRoots($event);
}
public function postRemove($event)
{
$this->keepAggregateRoots($event);
}
public function postFlush($event)
{
/** #var AggregateRoot $entity */
VarDumper::dump($this->entities);die();
foreach ($this->entities as $entity) {
foreach ($entity->releaseEvents() as $anEvent) {
$this->dispatcher->dispatch($anEvent);
}
}
$this->entities = array();
}
private function keepAggregateRoots($event)
{
$entity = $event->getEntity();
if (!($entity instanceof AggregateRoot)) {
return;
}
$this->entities[] = $entity;
}
}
but when dumping the captured entities on the postFlush VarDumper::dump($this->entities);
Im just getting empty array result.
NOTE:
TransactionItem extends AggregateRoot but Payment does not
but at least Im expecting TransactionItem to be present.
Does just adding child relationships will not include it in the doctrine events?
How to manually tell doctrine that TransactionItem should be present in the postFlush event?
EDIT: Dumping inside postUpdate is not being called.
public function postUpdate($event)
{
$this->keepAggregateRoots($event);
VarDumper::dump('Inside postUpdate');
VarDumper::dump($this->entities);die();
}
I'm trying to make some relationships in Doctrine
LancamentoConf.orm.yml:
Amz\FinanceiroBundle\Entity\LancamentoConf:
type: entity
table: amz_financeiro_lancamento_conf
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
active:
type: string
length: 1
...
manyToOne:
conta:
targetEntity: ContaConf
inversedBy: contajoinlancamentoconf
joinColumn:
name: amz_financeiro_conta_conf_id
referencedColumnName: id
manyToOne:
centrodecusto:
targetEntity: Amz\AmzBundle\Entity\CentroDeCustoConf
inversedBy: lancamentoconf
joinColumn:
name: amz_centro_de_custo_conf_id
referencedColumnName: id
ContaConf.orm.yml:
Amz\FinanceiroBundle\Entity\ContaConf:
type: entity
table: amz_financeiro_conta_conf
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
active:
type: string
length: 1
...
oneToMany:
contajoinlancamentoconf:
targetEntity: LancamentoConf
mappedBy: lancamentoconf
But just "centrodecusto" relationship is working...
I noticed that just the last one relationship in LancamentoConf.orm.yml works. If I change the order ("centrodecusto" first and "conta" second), "centrodecusto" will work fine...
You're problem is duplicated manyToOne section, there should be only one definition and inside you could define several elements:
LancamentoConf.orm.yml:
Amz\FinanceiroBundle\Entity\LancamentoConf:
type: entity
table: amz_financeiro_lancamento_conf
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
active:
type: string
length: 1
...
manyToOne:
conta:
targetEntity: ContaConf
inversedBy: contajoinlancamentoconf
joinColumn:
name: amz_financeiro_conta_conf_id
referencedColumnName: id
centrodecusto:
targetEntity: Amz\AmzBundle\Entity\CentroDeCustoConf
inversedBy: lancamentoconf
joinColumn:
name: amz_centro_de_custo_conf_id
referencedColumnName: id