From 92ff9e081dd27951bf3588bb36b31563337e7481 Mon Sep 17 00:00:00 2001 From: lahirulakruwan Date: Fri, 3 Jan 2025 08:55:11 +0530 Subject: [PATCH 1/3] Student File upload changes added --- campus/bffs/enrollment/api/Dependencies.toml | 14 +- campus/bffs/enrollment/api/client.bal | 11 +- campus/bffs/enrollment/api/service.bal | 168 +++- campus/bffs/enrollment/api/types.bal | 49 + .../graphql_client/enrollment.graphql | 23 + .../graphql_client_cg_src/client.bal | 10 +- .../graphql_client_cg_src/types.bal | 60 ++ .../enrollment/graphql_client/schema.graphql | 81 +- .../enrollment/graphql_client/schema.json | 947 ++++++++++++++++-- 9 files changed, 1292 insertions(+), 71 deletions(-) diff --git a/campus/bffs/enrollment/api/Dependencies.toml b/campus/bffs/enrollment/api/Dependencies.toml index d621aef7..1e1d3bbf 100644 --- a/campus/bffs/enrollment/api/Dependencies.toml +++ b/campus/bffs/enrollment/api/Dependencies.toml @@ -15,7 +15,9 @@ dependencies = [ {org = "ballerina", name = "graphql"}, {org = "ballerina", name = "http"}, {org = "ballerina", name = "io"}, + {org = "ballerina", name = "lang.array"}, {org = "ballerina", name = "log"}, + {org = "ballerina", name = "mime"}, {org = "ballerina", name = "test"}, {org = "ballerinai", name = "observe"} ] @@ -108,7 +110,7 @@ modules = [ [[package]] org = "ballerina" name = "http" -version = "2.10.17" +version = "2.10.19" dependencies = [ {org = "ballerina", name = "auth"}, {org = "ballerina", name = "cache"}, @@ -140,7 +142,7 @@ modules = [ [[package]] org = "ballerina" name = "io" -version = "1.6.1" +version = "1.6.3" dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.value"} @@ -185,6 +187,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.__internal"} ] +modules = [ + {org = "ballerina", packageName = "lang.array", moduleName = "lang.array"} +] [[package]] org = "ballerina" @@ -274,6 +279,9 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.int"} ] +modules = [ + {org = "ballerina", packageName = "mime", moduleName = "mime"} +] [[package]] org = "ballerina" @@ -357,7 +365,7 @@ dependencies = [ [[package]] org = "ballerina" name = "websocket" -version = "2.10.2" +version = "2.10.3" dependencies = [ {org = "ballerina", name = "auth"}, {org = "ballerina", name = "constraint"}, diff --git a/campus/bffs/enrollment/api/client.bal b/campus/bffs/enrollment/api/client.bal index c20529a1..d8b36eb0 100644 --- a/campus/bffs/enrollment/api/client.bal +++ b/campus/bffs/enrollment/api/client.bal @@ -35,11 +35,12 @@ public isolated client class GraphqlClient { return check performDataBinding(graphqlResponse, GetPersonsResponse); } remote isolated function getPersonById(int id) returns GetPersonByIdResponse|graphql:ClientError { - string query = string `query getPersonById($id:Int!) {person_by_id(id:$id) {id preferred_name full_name date_of_birth sex asgardeo_id jwt_sub_id created updated jwt_email mailing_address {city {id name {name_en name_si name_ta} district {id name {name_en}}} street_address phone id} phone organization {id description notes address {id} avinya_type {id name} name {name_en} parent_organizations {id name {name_en}}} avinya_type_id notes nic_no passport_no id_no email street_address digital_id avinya_phone bank_name bank_account_number bank_account_name academy_org_id bank_branch created_by updated_by current_job}}`; + string query = string `query getPersonById($id:Int!) {person_by_id(id:$id) {id preferred_name full_name date_of_birth sex asgardeo_id jwt_sub_id created updated jwt_email mailing_address {city {id name {name_en name_si name_ta} district {id name {name_en}}} street_address phone id} phone organization {id description notes address {id} avinya_type {id name} name {name_en} parent_organizations {id name {name_en}}} avinya_type_id notes nic_no passport_no id_no email street_address digital_id avinya_phone bank_name bank_account_number bank_account_name academy_org_id bank_branch created_by updated_by current_job document_list {document document_type}}}`; map variables = {"id": id}; json graphqlResponse = check self.graphqlClient->executeWithType(query, variables); return check performDataBinding(graphqlResponse, GetPersonByIdResponse); } + remote isolated function updatePerson(Person person, City? permanent_address_city = (), Address? mailing_address = (), Address? permanent_address = (), City? mailing_address_city = ()) returns UpdatePersonResponse|graphql:ClientError { string query = string `mutation updatePerson($person:Person!,$permanent_address:Address,$permanent_address_city:City,$mailing_address:Address,$mailing_address_city:City) {update_person(person:$person,permanent_address:$permanent_address,permanent_address_city:$permanent_address_city,mailing_address:$mailing_address,mailing_address_city:$mailing_address_city) {id preferred_name full_name date_of_birth sex asgardeo_id jwt_sub_id created updated jwt_email permanent_address {city {id name {name_en name_si name_ta}} street_address phone id} mailing_address {city {id name {name_en name_si name_ta}} street_address phone id} phone organization {id description notes address {id} avinya_type {id name} name {name_en} parent_organizations {id name {name_en}}} avinya_type_id notes nic_no passport_no id_no email street_address digital_id avinya_phone bank_name bank_account_number bank_account_name academy_org_id bank_branch created_by updated_by current_job}}`; map variables = {"permanent_address_city": permanent_address_city, "mailing_address": mailing_address, "person": person, "permanent_address": permanent_address, "mailing_address_city": mailing_address_city}; @@ -65,9 +66,15 @@ public isolated client class GraphqlClient { return check performDataBinding(graphqlResponse, GetAllOrganizationsResponse); } remote isolated function insertPerson(Person person, Address? mailing_address = (), City? mailing_address_city = ()) returns InsertPersonResponse|graphql:ClientError { - string query = string `mutation insertPerson($person:Person!,$mailing_address:Address,$mailing_address_city:City) {insert_person(person:$person,mailing_address:$mailing_address,mailing_address_city:$mailing_address_city) {id preferred_name full_name date_of_birth sex asgardeo_id jwt_sub_id created updated jwt_email permanent_address {city {id name {name_en name_si name_ta}} street_address phone id} mailing_address {city {id name {name_en name_si name_ta}} street_address phone id} phone organization {id description notes address {id} avinya_type {id name} name {name_en} parent_organizations {id name {name_en}}} avinya_type_id notes nic_no passport_no id_no email street_address digital_id avinya_phone bank_name bank_account_number bank_account_name academy_org_id bank_branch created_by updated_by current_job}}`; + string query = string `mutation insertPerson($person:Person!,$mailing_address:Address,$mailing_address_city:City) {insert_person(person:$person,mailing_address:$mailing_address,mailing_address_city:$mailing_address_city) {id preferred_name full_name date_of_birth sex asgardeo_id jwt_sub_id created updated jwt_email permanent_address {city {id name {name_en name_si name_ta}} street_address phone id} mailing_address {city {id name {name_en name_si name_ta}} street_address phone id} phone organization {id description notes address {id} avinya_type {id name} name {name_en} parent_organizations {id name {name_en}}} avinya_type_id notes nic_no passport_no id_no email street_address digital_id avinya_phone bank_name bank_account_number bank_account_name academy_org_id bank_branch created_by updated_by current_job documents_id}}`; map variables = {"mailing_address": mailing_address, "person": person, "mailing_address_city": mailing_address_city}; json graphqlResponse = check self.graphqlClient->executeWithType(query, variables); return check performDataBinding(graphqlResponse, InsertPersonResponse); } + remote isolated function uploadDocument(UserDocument user_document) returns UploadDocumentResponse|graphql:ClientError { + string query = string `mutation uploadDocument($user_document:UserDocument!) {upload_document(user_document:$user_document) {id folder_id nic_front_id nic_back_id birth_certificate_front_id birth_certificate_back_id ol_certificate_id al_certificate_id additional_certificate_01_id additional_certificate_02_id additional_certificate_03_id additional_certificate_04_id additional_certificate_05_id}}`; + map variables = {"user_document": user_document}; + json graphqlResponse = check self.graphqlClient->executeWithType(query, variables); + return check performDataBinding(graphqlResponse, UploadDocumentResponse); + } } diff --git a/campus/bffs/enrollment/api/service.bal b/campus/bffs/enrollment/api/service.bal index c376358a..1fcd8f58 100644 --- a/campus/bffs/enrollment/api/service.bal +++ b/campus/bffs/enrollment/api/service.bal @@ -1,6 +1,9 @@ import ballerina/graphql; import ballerina/http; +import ballerina/io; +import ballerina/lang.array; import ballerina/log; +import ballerina/mime; public function initClientConfig() returns ConnectionConfig { ConnectionConfig _clientConig = {}; @@ -155,11 +158,11 @@ service / on new http:Listener(9095) { City? permanent_address_city = permanent_address?.city; City? mailing_address_city = mailing_address?.city; - if(permanent_address is Address){ + if (permanent_address is Address) { permanent_address.city = (); } - if(mailing_address is Address){ + if (mailing_address is Address) { mailing_address.city = (); } @@ -183,7 +186,7 @@ service / on new http:Listener(9095) { } } - resource function post add_person(@http:Payload Person person) returns Person|error { + resource function post add_person(@http:Payload Person person) returns Person|ErrorDetail|error { Address? mailing_address = person?.mailing_address; City? mailing_address_city = mailing_address?.city; @@ -201,13 +204,164 @@ service / on new http:Listener(9095) { return person_record; } else { log:printError("Error while processing Application record received", person_record); - return error("Error while processing Application record received: " + person_record.message() + - ":: Detail: " + person_record.detail().toString()); + return { + "message": person_record.message().toString(), + "errorCode": "500" + }; } } else { log:printError("Error while creating application", addPersonResponse); - return error("Error while creating application: " + addPersonResponse.message() + - ":: Detail: " + addPersonResponse.detail().toString()); + return { + "message": addPersonResponse.message().toString(), + "errorCode": "500" + }; + } + } + resource function post upload_document(http:Request req) returns UserDocument|ErrorDetail|error { + + UserDocument document = {}; + UserDocument document_details = {}; + int document_row_id = 0; + string document_type = ""; + + if (req.getContentType().startsWith("multipart/form-data")) { + + mime:Entity[] bodyParts = check req.getBodyParts(); + string base64EncodedStringDocument = ""; + + foreach var part in bodyParts { + mime:ContentDisposition contentDisposition = part.getContentDisposition(); + + if (contentDisposition.name == "document_details") { + + json document_details_in_json = check part.getJson(); + document_details = check document_details_in_json.cloneWithType(UserDocument); + document_row_id = document_details?.id ?: 0; + document_type = document_details?.document_type ?: ""; + + } else if (contentDisposition.name == "document") { + + stream|mime:ParserError str = part.getByteStream(); + + if str is stream { + + byte[] allBytes = []; // Initialize an empty byte array + + // Iterate through the stream and collect all chunks + error? e = str.forEach(function(byte[] chunk) { + array:push(allBytes, ...chunk); // Efficiently append all bytes from chunk + }); + + byte[] base64EncodedDocument = (check mime:base64Encode(allBytes)); + base64EncodedStringDocument = check string:fromBytes(base64EncodedDocument); + + } + } + + } + + document = { + id: document_row_id, + document_type: document_type, + document: base64EncodedStringDocument + }; + + } + + UploadDocumentResponse|graphql:ClientError uploadDocumentResponse = globalDataClient->uploadDocument(document); + if (uploadDocumentResponse is UploadDocumentResponse) { + UserDocument|error document_record = uploadDocumentResponse.upload_document.cloneWithType(UserDocument); + if (document_record is UserDocument) { + return document_record; + } else { + log:printError("Error while processing Application record received", document_record); + return { + "message": document_record.message().toString(), + "errorCode": "500" + }; + } + } else { + log:printError("Error while creating application", uploadDocumentResponse); + return { + "message": uploadDocumentResponse.message().toString(), + "errorCode": "500" + }; } } + // resource function post add_person(http:Request req) returns Person|error { + // UserDocumentList[] documents = []; + // Person person = {}; + // Address? mailing_address = {}; + // City? mailing_address_city = {}; + + // if (req.getContentType().startsWith("multipart/form-data")) { + // mime:Entity[] bodyParts = check req.getBodyParts(); + + // foreach var part in bodyParts { + // mime:ContentDisposition contentDisposition = part.getContentDisposition(); + + // if (contentDisposition.name == "person") { + // // Extract JSON string and convert to Person record + // json personJson = check part.getJson(); + // person = check personJson.cloneWithType(Person); + // mailing_address = person?.mailing_address; + // mailing_address_city = mailing_address?.city; + + // if (mailing_address is Address) { + // mailing_address.city = (); + // } + + // person.mailing_address = (); + + // } else if (contentDisposition.name == "documents") { + + // // Get the filename from Content-Disposition + // string? documentName = contentDisposition.fileName; + + // stream|mime:ParserError str = part.getByteStream(); + + // //Extract file name without extension + // string:RegExp r = re `\.`; + // string[] split_document_name = r.split(documentName ?: ""); + + // if str is stream { + + // byte[] allBytes = []; // Initialize an empty byte array + + // // Iterate through the stream and collect all chunks + // error? e = str.forEach(function(byte[] chunk) { + // array:push(allBytes, ...chunk); // Efficiently append all bytes from chunk + // }); + + // byte[] base64EncodedDocument = (check mime:base64Encode(allBytes)); + // string base64EncodedStringDocument = check string:fromBytes(base64EncodedDocument); + + // UserDocumentList document = { + // document_name: split_document_name[0], + // document: base64EncodedStringDocument + + // }; + // //io:println(document); + // documents.push(document); + // } + // } + + // } + // } + // InsertPersonResponse|graphql:ClientError addPersonResponse = globalDataClient->insertPerson(documents, person, mailing_address, mailing_address_city); + // if (addPersonResponse is InsertPersonResponse) { + // Person|error person_record = addPersonResponse.insert_person.cloneWithType(Person); + // if (person_record is Person) { + // return person_record; + // } else { + // log:printError("Error while processing Application record received", person_record); + // return error("Error while processing Application record received: " + person_record.message() + + // ":: Detail: " + person_record.detail().toString()); + // } + // } else { + // log:printError("Error while creating application", addPersonResponse); + // return error("Error while creating application: " + addPersonResponse.message() + + // ":: Detail: " + addPersonResponse.detail().toString()); + // } + // } } diff --git a/campus/bffs/enrollment/api/types.bal b/campus/bffs/enrollment/api/types.bal index 0ab9fc86..41b4a14a 100644 --- a/campus/bffs/enrollment/api/types.bal +++ b/campus/bffs/enrollment/api/types.bal @@ -105,16 +105,42 @@ public type Person record { string? full_name?; string? nic_no?; int? phone?; + UserDocument[]? documentList?; int? organization_id?; int? updated_by?; string? academy_org_name?; string? asgardeo_id?; + int? documents_id?; string? updated?; string? preferred_name?; string? jwt_sub_id?; int? academy_org_id?; }; +public type UserDocument record { + string? birth_certificate_back_id?; + string? additional_certificate_01_id?; + string? additional_certificate_02_id?; + string? nic_back_id?; + string? document?; + string? additional_certificate_05_id?; + string? additional_certificate_04_id?; + string? additional_certificate_03_id?; + string? record_type?; + string? al_certificate_id?; + string? nic_front_id?; + string? ol_certificate_id?; + string? birth_certificate_front_id?; + int? id?; + string? folder_id?; + string? document_type?; +}; + +public type ErrorDetail record { + string message; + int errorCode; +}; + public type GetPersonsResponse record {| map __extensions?; record {| @@ -267,6 +293,10 @@ public type GetPersonByIdResponse record {| int? created_by; int? updated_by; string? current_job; + record {| + string? document; + string? document_type; + |}[]? document_list; |}? person_by_id; |}; @@ -488,5 +518,24 @@ public type InsertPersonResponse record {| int? created_by; int? updated_by; string? current_job; + int? documents_id; |}? insert_person; |}; +public type UploadDocumentResponse record {| + map __extensions?; + record {| + int? id; + string? folder_id; + string? nic_front_id; + string? nic_back_id; + string? birth_certificate_front_id; + string? birth_certificate_back_id; + string? ol_certificate_id; + string? al_certificate_id; + string? additional_certificate_01_id; + string? additional_certificate_02_id; + string? additional_certificate_03_id; + string? additional_certificate_04_id; + string? additional_certificate_05_id; + |}? upload_document; +|}; diff --git a/campus/bffs/enrollment/graphql_client/enrollment.graphql b/campus/bffs/enrollment/graphql_client/enrollment.graphql index de66aee4..25fb5514 100644 --- a/campus/bffs/enrollment/graphql_client/enrollment.graphql +++ b/campus/bffs/enrollment/graphql_client/enrollment.graphql @@ -148,6 +148,10 @@ query getPersonById($id: Int!) { created_by updated_by current_job + document_list { + document + document_type + } } } @@ -384,5 +388,24 @@ mutation insertPerson( created_by updated_by current_job + documents_id + } +} + +mutation uploadDocument($user_document: UserDocument!) { + upload_document(user_document: $user_document) { + id + folder_id + nic_front_id + nic_back_id + birth_certificate_front_id + birth_certificate_back_id + ol_certificate_id + al_certificate_id + additional_certificate_01_id + additional_certificate_02_id + additional_certificate_03_id + additional_certificate_04_id + additional_certificate_05_id } } diff --git a/campus/bffs/enrollment/graphql_client/graphql_client_cg_src/client.bal b/campus/bffs/enrollment/graphql_client/graphql_client_cg_src/client.bal index b9ffc3be..023c2005 100644 --- a/campus/bffs/enrollment/graphql_client/graphql_client_cg_src/client.bal +++ b/campus/bffs/enrollment/graphql_client/graphql_client_cg_src/client.bal @@ -34,7 +34,7 @@ public isolated client class GraphqlClient { return check performDataBinding(graphqlResponse, GetPersonsResponse); } remote isolated function getPersonById(int id) returns GetPersonByIdResponse|graphql:ClientError { - string query = string `query getPersonById($id:Int!) {person_by_id(id:$id) {id preferred_name full_name date_of_birth sex asgardeo_id jwt_sub_id created updated jwt_email mailing_address {city {id name {name_en name_si name_ta} district {id name {name_en}}} street_address phone id} phone organization {id description notes address {id} avinya_type {id name} name {name_en} parent_organizations {id name {name_en}}} avinya_type_id notes nic_no passport_no id_no email street_address digital_id avinya_phone bank_name bank_account_number bank_account_name academy_org_id bank_branch created_by updated_by current_job}}`; + string query = string `query getPersonById($id:Int!) {person_by_id(id:$id) {id preferred_name full_name date_of_birth sex asgardeo_id jwt_sub_id created updated jwt_email mailing_address {city {id name {name_en name_si name_ta} district {id name {name_en}}} street_address phone id} phone organization {id description notes address {id} avinya_type {id name} name {name_en} parent_organizations {id name {name_en}}} avinya_type_id notes nic_no passport_no id_no email street_address digital_id avinya_phone bank_name bank_account_number bank_account_name academy_org_id bank_branch created_by updated_by current_job document_list {document document_type}}}`; map variables = {"id": id}; json graphqlResponse = check self.graphqlClient->executeWithType(query, variables); return check performDataBinding(graphqlResponse, GetPersonByIdResponse); @@ -70,9 +70,15 @@ public isolated client class GraphqlClient { return check performDataBinding(graphqlResponse, GetAllOrganizationsResponse); } remote isolated function insertPerson(Person person, Address? mailing_address = (), City? mailing_address_city = ()) returns InsertPersonResponse|graphql:ClientError { - string query = string `mutation insertPerson($person:Person!,$mailing_address:Address,$mailing_address_city:City) {insert_person(person:$person,mailing_address:$mailing_address,mailing_address_city:$mailing_address_city) {id preferred_name full_name date_of_birth sex asgardeo_id jwt_sub_id created updated jwt_email permanent_address {city {id name {name_en name_si name_ta}} street_address phone id} mailing_address {city {id name {name_en name_si name_ta}} street_address phone id} phone organization {id description notes address {id} avinya_type {id name} name {name_en} parent_organizations {id name {name_en}}} avinya_type_id notes nic_no passport_no id_no email street_address digital_id avinya_phone bank_name bank_account_number bank_account_name academy_org_id bank_branch created_by updated_by current_job}}`; + string query = string `mutation insertPerson($person:Person!,$mailing_address:Address,$mailing_address_city:City) {insert_person(person:$person,mailing_address:$mailing_address,mailing_address_city:$mailing_address_city) {id preferred_name full_name date_of_birth sex asgardeo_id jwt_sub_id created updated jwt_email permanent_address {city {id name {name_en name_si name_ta}} street_address phone id} mailing_address {city {id name {name_en name_si name_ta}} street_address phone id} phone organization {id description notes address {id} avinya_type {id name} name {name_en} parent_organizations {id name {name_en}}} avinya_type_id notes nic_no passport_no id_no email street_address digital_id avinya_phone bank_name bank_account_number bank_account_name academy_org_id bank_branch created_by updated_by current_job documents_id}}`; map variables = {"mailing_address": mailing_address, "person": person, "mailing_address_city": mailing_address_city}; json graphqlResponse = check self.graphqlClient->executeWithType(query, variables); return check performDataBinding(graphqlResponse, InsertPersonResponse); } + remote isolated function uploadDocument(UserDocument user_document) returns UploadDocumentResponse|graphql:ClientError { + string query = string `mutation uploadDocument($user_document:UserDocument!) {upload_document(user_document:$user_document) {id folder_id nic_front_id nic_back_id birth_certificate_front_id birth_certificate_back_id ol_certificate_id al_certificate_id additional_certificate_01_id additional_certificate_02_id additional_certificate_03_id additional_certificate_04_id additional_certificate_05_id}}`; + map variables = {"user_document": user_document}; + json graphqlResponse = check self.graphqlClient->executeWithType(query, variables); + return check performDataBinding(graphqlResponse, UploadDocumentResponse); + } } diff --git a/campus/bffs/enrollment/graphql_client/graphql_client_cg_src/types.bal b/campus/bffs/enrollment/graphql_client/graphql_client_cg_src/types.bal index c0a7539e..fa9cc955 100644 --- a/campus/bffs/enrollment/graphql_client/graphql_client_cg_src/types.bal +++ b/campus/bffs/enrollment/graphql_client/graphql_client_cg_src/types.bal @@ -274,6 +274,20 @@ public type Inventory record { int? person_id?; }; +public type MonthlyLeaveDates record { + string? leave_dates?; + int? month?; + int[] leave_dates_list?; + int? year?; + string? created?; + int? total_days_in_month?; + int? organization_id?; + int? id?; + anydata? daily_amount?; + string? updated?; + string? record_type?; +}; + public type Organization record { string? notes?; string? name_ta?; @@ -282,6 +296,7 @@ public type Organization record { string? name_si?; int? avinya_type?; string? description?; + int? active?; int[]? child_organizations_for_dashboard?; string? record_type?; int[]? parent_organizations?; @@ -321,10 +336,12 @@ public type Person record { string? full_name?; string? nic_no?; int? phone?; + UserDocument[]? documentList?; int? organization_id?; int? updated_by?; string? academy_org_name?; string? asgardeo_id?; + int? documents_id?; string? updated?; string? preferred_name?; string? jwt_sub_id?; @@ -406,6 +423,25 @@ public type Supply record { int? person_id?; }; +public type UserDocument record { + string? birth_certificate_back_id?; + string? additional_certificate_01_id?; + string? additional_certificate_02_id?; + string? nic_back_id?; + string? document?; + string? additional_certificate_05_id?; + string? additional_certificate_04_id?; + string? additional_certificate_03_id?; + string? record_type?; + string? al_certificate_id?; + string? nic_front_id?; + string? ol_certificate_id?; + string? birth_certificate_front_id?; + int? id?; + string? folder_id?; + string? document_type?; +}; + public type Vacancy record { int? organization_id?; string? name?; @@ -579,6 +615,10 @@ public type GetPersonByIdResponse record {| int? created_by; int? updated_by; string? current_job; + record {| + string? document; + string? document_type; + |}[]? document_list; |}? person_by_id; |}; @@ -801,5 +841,25 @@ public type InsertPersonResponse record {| int? created_by; int? updated_by; string? current_job; + int? documents_id; |}? insert_person; |}; + +public type UploadDocumentResponse record {| + map __extensions?; + record {| + int? id; + string? folder_id; + string? nic_front_id; + string? nic_back_id; + string? birth_certificate_front_id; + string? birth_certificate_back_id; + string? ol_certificate_id; + string? al_certificate_id; + string? additional_certificate_01_id; + string? additional_certificate_02_id; + string? additional_certificate_03_id; + string? additional_certificate_04_id; + string? additional_certificate_05_id; + |}? upload_document; +|}; diff --git a/campus/bffs/enrollment/graphql_client/schema.graphql b/campus/bffs/enrollment/graphql_client/schema.graphql index 06ef54a0..13e3913f 100644 --- a/campus/bffs/enrollment/graphql_client/schema.graphql +++ b/campus/bffs/enrollment/graphql_client/schema.graphql @@ -310,6 +310,12 @@ type AvinyaTypeData { description: String } +type CalendarMetaData { + id: Int + organization_id: Int + monthly_payment_amount: Decimal +} + input City { record_type: String = "city" id: Int @@ -384,6 +390,24 @@ type DistrictData { cities: [CityData!]! } +type DocumentsData { + id: Int + folder_id: String + nic_front_id: String + nic_back_id: String + birth_certificate_front_id: String + birth_certificate_back_id: String + ol_certificate_id: String + al_certificate_id: String + additional_certificate_01_id: String + additional_certificate_02_id: String + additional_certificate_03_id: String + additional_certificate_04_id: String + additional_certificate_05_id: String + document_type: String + document: String +} + input DutyParticipant { record_type: String = "duty_participant" id: Int @@ -607,6 +631,31 @@ type LocalizedName { name_si: String } +input MonthlyLeaveDates { + record_type: String = "monthly_leave_dates" + id: Int + year: Int + month: Int + total_days_in_month: Int + organization_id: Int + leave_dates_list: [Int!]! + leave_dates: String + daily_amount: Decimal + created: String + updated: String +} + +type MonthlyLeaveDatesData { + id: Int + year: Int + month: Int + organization_id: Int + leave_dates_list: [Int!] + daily_amount: Decimal + created: String + updated: String +} + type Mutation { add_avinya_type(avinya_type: AvinyaType!): AvinyaTypeData update_avinya_type(avinya_type: AvinyaType!): AvinyaTypeData @@ -667,6 +716,9 @@ type Mutation { update_consumable_depletion(inventories: [Inventory!]!): [InventoryData!] update_person(person: Person!, permanent_address: Address, permanent_address_city: City, mailing_address: Address, mailing_address_city: City): PersonData insert_person(person: Person!, mailing_address: Address, mailing_address_city: City): PersonData + upload_document(user_document: UserDocument!): DocumentsData + add_monthly_leave_dates(monthly_leave_dates: MonthlyLeaveDates!): MonthlyLeaveDatesData + update_monthly_leave_dates(monthly_leave_dates: MonthlyLeaveDates!): MonthlyLeaveDatesData } input Organization { @@ -680,6 +732,7 @@ input Organization { phone: Int description: String notes: String + active: Int name_en: String name_ta: String name_si: String @@ -699,6 +752,7 @@ type OrganizationData { people: [PersonData!] vacancies: [VacancyData!] organization_metadata: [OrganizationMetaData!] + active: Int } type OrganizationMetaData { @@ -749,6 +803,8 @@ input Person { academy_org_name: String branch_code: String current_job: String + documents_id: Int + documentList: [UserDocument!] created_by: Int updated_by: Int } @@ -790,6 +846,8 @@ type PersonData { current_job: String created_by: Int updated_by: Int + documents_id: Int + document_list: [DocumentsData!] } type PlaceData { @@ -858,7 +916,7 @@ type Query { organization_structure(name: String, id: Int): OrganizationStructureData organizations(level: Int!): OrganizationStructureData organization(name: String, id: Int): OrganizationData - organizations_by_avinya_type(avinya_type: Int): [OrganizationData!] + organizations_by_avinya_type(avinya_type: Int, active: Int = 0): [OrganizationData!] student_list_by_parent(id: Int): [PersonData!] person(name: String, id: Int): PersonData person_by_digital_id(id: String): PersonData @@ -932,6 +990,8 @@ type Query { districts: [DistrictData!] cities(district_id: Int): [CityData!] all_organizations: [OrganizationData!] + monthly_leave_dates_record_by_id(organization_id: Int!, year: Int!, month: Int!): MonthlyLeaveDatesData + calendar_metadata_by_org_id(organization_id: Int!): CalendarMetaData } input ResourceAllocation { @@ -1043,6 +1103,25 @@ type TotalActivityParticipantAttendanceCountByDateData { daily_total: Int } +input UserDocument { + record_type: String = "user_document" + id: Int + folder_id: String + nic_front_id: String + nic_back_id: String + birth_certificate_front_id: String + birth_certificate_back_id: String + ol_certificate_id: String + al_certificate_id: String + additional_certificate_01_id: String + additional_certificate_02_id: String + additional_certificate_03_id: String + additional_certificate_04_id: String + additional_certificate_05_id: String + document_type: String + document: String +} + input Vacancy { record_type: String = "vacancy" id: Int diff --git a/campus/bffs/enrollment/graphql_client/schema.json b/campus/bffs/enrollment/graphql_client/schema.json index 1479556a..f9b259b4 100644 --- a/campus/bffs/enrollment/graphql_client/schema.json +++ b/campus/bffs/enrollment/graphql_client/schema.json @@ -423,6 +423,36 @@ }, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "documents_id", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "document_list", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "DocumentsData", + "ofType": null + } + } + }, + "isDeprecated": false, + "deprecationReason": null } ], "inputFields": null, @@ -713,6 +743,15 @@ "ofType": null }, "defaultValue": null + }, + { + "name": "active", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": "0" } ], "type": { @@ -3113,6 +3152,82 @@ }, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "monthly_leave_dates_record_by_id", + "args": [ + { + "name": "organization_id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "year", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "month", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "MonthlyLeaveDatesData", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "calendar_metadata_by_org_id", + "args": [ + { + "name": "organization_id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "CalendarMetaData", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null } ], "inputFields": null, @@ -5799,6 +5914,17 @@ }, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "active", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null } ], "inputFields": null, @@ -6980,6 +7106,112 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "MonthlyLeaveDatesData", + "fields": [ + { + "name": "id", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "year", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "month", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "organization_id", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "leave_dates_list", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "daily_amount", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Decimal", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "created", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "updated", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "Mutation", @@ -8753,36 +8985,111 @@ }, "isDeprecated": false, "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "ProvinceData", - "fields": [ + }, { - "name": "id", - "args": [], + "name": "upload_document", + "args": [ + { + "name": "user_document", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "UserDocument", + "ofType": null + } + }, + "defaultValue": null + } + ], "type": { - "kind": "SCALAR", - "name": "Int", + "kind": "OBJECT", + "name": "DocumentsData", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "name", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", + "name": "add_monthly_leave_dates", + "args": [ + { + "name": "monthly_leave_dates", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "MonthlyLeaveDates", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "MonthlyLeaveDatesData", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "update_monthly_leave_dates", + "args": [ + { + "name": "monthly_leave_dates", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "MonthlyLeaveDates", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "MonthlyLeaveDatesData", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "ProvinceData", + "fields": [ + { + "name": "id", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", "name": "LocalizedName", "ofType": null } @@ -8884,6 +9191,127 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "MonthlyLeaveDates", + "fields": null, + "inputFields": [ + { + "name": "record_type", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": "\"monthly_leave_dates\"" + }, + { + "name": "id", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "year", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "month", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "total_days_in_month", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "organization_id", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "leave_dates_list", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + } + }, + "defaultValue": null + }, + { + "name": "leave_dates", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "daily_amount", + "type": { + "kind": "SCALAR", + "name": "Decimal", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "created", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "updated", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "EvaluationCriteriaAnswerOptionData", @@ -9272,6 +9700,32 @@ }, "defaultValue": null }, + { + "name": "documents_id", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "documentList", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "UserDocument", + "ofType": null + } + } + }, + "defaultValue": null + }, { "name": "created_by", "type": { @@ -9907,6 +10361,15 @@ }, "defaultValue": null }, + { + "name": "active", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, { "name": "name_en", "type": { @@ -9941,7 +10404,7 @@ }, { "kind": "INPUT_OBJECT", - "name": "EducationExperience", + "name": "UserDocument", "fields": null, "inputFields": [ { @@ -9951,7 +10414,7 @@ "name": "String", "ofType": null }, - "defaultValue": "\"education_experience\"" + "defaultValue": "\"user_document\"" }, { "name": "id", @@ -9963,16 +10426,16 @@ "defaultValue": null }, { - "name": "person_id", + "name": "folder_id", "type": { "kind": "SCALAR", - "name": "Int", + "name": "String", "ofType": null }, "defaultValue": null }, { - "name": "school", + "name": "nic_front_id", "type": { "kind": "SCALAR", "name": "String", @@ -9981,7 +10444,7 @@ "defaultValue": null }, { - "name": "start_date", + "name": "nic_back_id", "type": { "kind": "SCALAR", "name": "String", @@ -9990,7 +10453,7 @@ "defaultValue": null }, { - "name": "end_date", + "name": "birth_certificate_front_id", "type": { "kind": "SCALAR", "name": "String", @@ -9999,41 +10462,195 @@ "defaultValue": null }, { - "name": "evaluation_id", + "name": "birth_certificate_back_id", "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - } + "kind": "SCALAR", + "name": "String", + "ofType": null }, "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "DutyRotationMetaData", - "fields": [ + }, { - "name": "id", - "args": [], + "name": "ol_certificate_id", "type": { "kind": "SCALAR", - "name": "Int", + "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null + "defaultValue": null + }, + { + "name": "al_certificate_id", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "additional_certificate_01_id", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "additional_certificate_02_id", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "additional_certificate_03_id", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "additional_certificate_04_id", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "additional_certificate_05_id", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "document_type", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "document", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "EducationExperience", + "fields": null, + "inputFields": [ + { + "name": "record_type", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": "\"education_experience\"" + }, + { + "name": "id", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "person_id", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "school", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "start_date", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "end_date", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "evaluation_id", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "DutyRotationMetaData", + "fields": [ + { + "name": "id", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null }, { "name": "start_date", @@ -10312,6 +10929,181 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "DocumentsData", + "fields": [ + { + "name": "id", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "folder_id", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nic_front_id", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nic_back_id", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "birth_certificate_front_id", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "birth_certificate_back_id", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "ol_certificate_id", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "al_certificate_id", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "additional_certificate_01_id", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "additional_certificate_02_id", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "additional_certificate_03_id", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "additional_certificate_04_id", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "additional_certificate_05_id", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "document_type", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "document", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "INPUT_OBJECT", "name": "Supply", @@ -10503,6 +11295,49 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "CalendarMetaData", + "fields": [ + { + "name": "id", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "organization_id", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "monthly_payment_amount", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Decimal", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "AssetData", From 9ba4ef220870619731fc1da2723b9f30689708f5 Mon Sep 17 00:00:00 2001 From: YujithIsura Date: Mon, 6 Jan 2025 11:32:46 +0530 Subject: [PATCH 2/3] bug fixed in avinya type of student update --- .../enrollment/lib/widgets/student_update.dart | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/campus/frontend/lib/avinya/enrollment/lib/widgets/student_update.dart b/campus/frontend/lib/avinya/enrollment/lib/widgets/student_update.dart index 591c3edc..9aa738de 100644 --- a/campus/frontend/lib/avinya/enrollment/lib/widgets/student_update.dart +++ b/campus/frontend/lib/avinya/enrollment/lib/widgets/student_update.dart @@ -772,13 +772,16 @@ class _StudentUpdateState extends State { } // Determine the Avinya Type ID - final int? avinyaTypeId = (userPerson.date_of_birth != null && - calculateAge(userPerson.date_of_birth) != null && - calculateAge(userPerson.date_of_birth)! < 19) - ? 103 // Auto-select Future Enrollees if under 18 - : (userPerson.avinya_type_id ?? - userPerson.avinya_type - ?.id); // Fallback to avinya_type?.id if avinya_type_id is null + // final int? avinyaTypeId = (userPerson.date_of_birth != null && + // calculateAge(userPerson.date_of_birth) != null && + // calculateAge(userPerson.date_of_birth)! < 19) + // ? 103 // Auto-select Future Enrollees if under 18 + // : (userPerson.avinya_type_id ?? + // userPerson.avinya_type + // ?.id); // Fallback to avinya_type?.id if avinya_type_id is null + + final int? avinyaTypeId = + (userPerson.avinya_type_id ?? userPerson.avinya_type?.id); // Filter avinyaTypes based on the selected IDs final filteredAvinyaTypes = avinyaTypes.where((org) { From 51b708dadde0e5b66297813cc1e70e274101b5aa Mon Sep 17 00:00:00 2001 From: YujithIsura Date: Mon, 6 Jan 2025 11:34:24 +0530 Subject: [PATCH 3/3] student file upload WIP --- .../avinya/enrollment/lib/data/person.dart | 99 ++++++- .../lib/widgets/file_upload_widget.dart | 143 +++++++++++ .../lib/widgets/student_create.dart | 242 ++++++++++-------- .../lib/avinya/enrollment/pubspec.yaml | 3 + .../flutter/generated_plugin_registrant.cc | 4 + .../linux/flutter/generated_plugins.cmake | 1 + .../Flutter/GeneratedPluginRegistrant.swift | 2 + campus/frontend/pubspec.yaml | 3 + .../flutter/generated_plugin_registrant.cc | 3 + .../windows/flutter/generated_plugins.cmake | 1 + 10 files changed, 385 insertions(+), 116 deletions(-) create mode 100644 campus/frontend/lib/avinya/enrollment/lib/widgets/file_upload_widget.dart diff --git a/campus/frontend/lib/avinya/enrollment/lib/data/person.dart b/campus/frontend/lib/avinya/enrollment/lib/data/person.dart index f3ca3f0b..e8570a7e 100644 --- a/campus/frontend/lib/avinya/enrollment/lib/data/person.dart +++ b/campus/frontend/lib/avinya/enrollment/lib/data/person.dart @@ -1,11 +1,13 @@ import 'dart:developer'; -import 'package:gallery/avinya/enrollment/lib/screens/students_screen.dart'; +import 'dart:typed_data'; import 'package:gallery/widgets/success_message.dart'; import 'package:gallery/widgets/error_message.dart'; import 'package:flutter/material.dart'; import 'package:gallery/config/app_config.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; +import 'package:http_parser/http_parser.dart'; +import 'package:mime/mime.dart'; class MainOrganization { int? id; @@ -490,12 +492,12 @@ Future createPerson(BuildContext context, Person person) async { if (response.statusCode == 201) { Person person = Person.fromJson(json.decode(response.body)); showSuccessToast("Student Profile Successfully Created!"); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => StudentsScreen(), - ), - ); + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => StudentsScreen(), + // ), + // ); return person; } else { log(response.body + " Status code =" + response.statusCode.toString()); @@ -648,3 +650,86 @@ Future> fetchCities(id) async { throw Exception('Failed to get City Data'); } } + +// Future uploadFile( +// Uint8List file, Map documentDetails) async { +// try { +// // Create the multipart request +// final uri = +// Uri.parse('${AppConfig.campusEnrollmentsBffApiUrl}/upload_document'); +// final request = http.MultipartRequest('POST', uri); + +// // Set the headers +// request.headers.addAll({ +// 'Authorization': 'Bearer ${AppConfig.campusBffApiKey}', +// 'accept': 'application/ld+json', +// }); + +// // Add the document_details as a JSON string +// request.fields['document_details'] = jsonEncode(documentDetails); + +// // Determine the MIME type of the file +// final mimeType = lookupMimeType(file.path) ?? 'application/octet-stream'; + +// // Attach the file to the request +// request.files.add( +// http.MultipartFile( +// 'document', // Key for the file in form-data +// file.readAsBytes().asStream(), +// file.lengthSync(), +// filename: basename(file.path), +// contentType: MediaType.parse(mimeType), +// ), +// ); + +// // Send the request +// final response = await request.send(); + +// return response; +// } catch (e) { +// print('Error uploading file: $e'); +// return null; +// } +// } + +Future uploadFile( + Uint8List fileBytes, Map documentDetails) async { + try { + // Create the multipart request + final uri = + Uri.parse('${AppConfig.campusEnrollmentsBffApiUrl}/upload_document'); + final request = http.MultipartRequest('POST', uri); + + // Set the headers + request.headers.addAll({ + 'Authorization': 'Bearer ${AppConfig.campusBffApiKey}', + 'accept': 'application/ld+json', + }); + + // Add the document_details as a JSON string + request.fields['document_details'] = jsonEncode(documentDetails); + + // Determine the MIME type of the file + final mimeType = lookupMimeType('', headerBytes: fileBytes) ?? + 'application/octet-stream'; + + // Attach the file to the request + request.files.add( + http.MultipartFile( + 'document', // Key for the file in form-data + Stream.fromIterable([fileBytes]), // Convert Uint8List to stream + fileBytes.length, // The length of the file + filename: 'document.png', // Adjust this as needed + contentType: MediaType.parse(mimeType), + ), + ); + + // Send the request + final response = await request.send(); + + return response; + } catch (e) { + print('Error uploading file: $e'); + return null; + } +} diff --git a/campus/frontend/lib/avinya/enrollment/lib/widgets/file_upload_widget.dart b/campus/frontend/lib/avinya/enrollment/lib/widgets/file_upload_widget.dart new file mode 100644 index 00000000..2c019647 --- /dev/null +++ b/campus/frontend/lib/avinya/enrollment/lib/widgets/file_upload_widget.dart @@ -0,0 +1,143 @@ +import 'dart:typed_data'; +import 'package:flutter/foundation.dart' show kIsWeb; +import 'package:flutter/material.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:file_picker/file_picker.dart'; +import 'package:gallery/avinya/enrollment/lib/data/person.dart'; + +class FileUploadWidget extends StatefulWidget { + final String documentType; + + const FileUploadWidget({Key? key, required this.documentType}) + : super(key: key); + + @override + State createState() => _FileUploadWidgetState(); +} + +class _FileUploadWidgetState extends State { + Uint8List? _selectedImageBytes; + String? _validationError; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Please upload the required file for "${widget.documentType}".', + style: const TextStyle(fontSize: 16.0, fontWeight: FontWeight.w400), + ), + const SizedBox(height: 20), + _buildFileInputField( + label: widget.documentType, + imageBytes: _selectedImageBytes, + fieldKey: widget.documentType, + onTap: () async { + final imageBytes = await _pickFile(); + if (imageBytes != null) { + var documentDetails = { + "id": 14, + "document_type": "additionalCertificate05" + }; + await uploadFile(imageBytes, documentDetails); + setState(() { + _selectedImageBytes = imageBytes; + _validationError = null; // Clear any errors + }); + } + }, + ), + const SizedBox(height: 20), + ], + ); + } + + Widget _buildFileInputField({ + required String label, + required Uint8List? imageBytes, + required String fieldKey, + required void Function()? onTap, + }) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: double.infinity, + child: InkWell( + onTap: onTap, + child: Container( + width: 330, + height: 90, + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(4.0), + ), + child: Row( + children: [ + imageBytes == null + ? const Icon( + Icons.add_a_photo_rounded, + size: 35.0, + color: Color(0xFF000080), + ) + : Image.memory( + imageBytes, + height: 80.0, + width: 80.0, + fit: BoxFit.cover, + ), + const SizedBox(width: 30.0), + RichText( + text: TextSpan( + text: label, + style: const TextStyle( + color: Color(0xFF000080), + fontStyle: FontStyle.normal, + fontSize: 18, + fontWeight: FontWeight.w500, + ), + children: const [ + TextSpan( + text: ' *', + style: TextStyle(color: Colors.red), + ), + ], + ), + ), + ], + ), + ), + ), + ), + if (_validationError != null) + Padding( + padding: const EdgeInsets.only(left: 12.0, top: 8.0), + child: Text( + _validationError!, + style: const TextStyle(color: Colors.red, fontSize: 12), + ), + ), + ], + ); + } + + Future _pickFile() async { + if (kIsWeb) { + // For Web: Use FilePicker + final result = await FilePicker.platform.pickFiles(type: FileType.image); + if (result != null && result.files.single.bytes != null) { + return result.files.single.bytes; + } + } else { + // For Mobile: Use ImagePicker + final XFile? pickedFile = + await ImagePicker().pickImage(source: ImageSource.gallery); + if (pickedFile != null) { + return await pickedFile.readAsBytes(); + } + } + return null; + } +} diff --git a/campus/frontend/lib/avinya/enrollment/lib/widgets/student_create.dart b/campus/frontend/lib/avinya/enrollment/lib/widgets/student_create.dart index 72611b90..6ebc2a27 100644 --- a/campus/frontend/lib/avinya/enrollment/lib/widgets/student_create.dart +++ b/campus/frontend/lib/avinya/enrollment/lib/widgets/student_create.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:gallery/avinya/enrollment/lib/widgets/file_upload_widget.dart'; import 'package:intl/intl.dart'; import 'package:gallery/avinya/enrollment/lib/data/person.dart'; @@ -327,60 +328,60 @@ class _StudentCreateState extends State { }), const SizedBox(height: 20), - _buildSectionTitle(context, 'More Information'), - ExpansionTile( - title: Text( - 'Click to expand more information', - style: Theme.of(context).textTheme.subtitle1, - ), - children: [ - // Guardian Information - _buildSectionTitle( - context, 'Guardian Information'), - _buildEditableField( - 'Guardian Name', userPerson.guardian_name, - (value) { - userPerson.guardian_name = value; - }, - validator: (value) => value!.isEmpty - ? 'Guardian name is required' - : null), - _buildEditableField( - 'Guardian Contact Number', - userPerson.guardian_contact_number - ?.toString() ?? - '', (value) { - userPerson.guardian_contact_number = - int.tryParse(value); - }, validator: _validatePhone), - - const SizedBox(height: 20), - - // O/L Results Section - _buildSectionTitle(context, 'O/L Results'), - // _buildEditableField('Subject 1', userPerson.ol_subject1, - // (value) { - // userPerson.ol_subject1 = value; - // }), - // _buildEditableField('Subject 2', userPerson.ol_subject2, - // (value) { - // userPerson.ol_subject2 = value; - // }), - // _buildEditableField('Subject 3', userPerson.ol_subject3, - // (value) { - // userPerson.ol_subject3 = value; - // }), - // _buildEditableField( - // 'Other Results', userPerson.ol_other_results, - // (value) { - // userPerson.ol_other_results = value; - // }), - - const SizedBox(height: 20), - - // Add other expandable sections here if needed - ], - ), + // _buildSectionTitle(context, 'More Information'), + // ExpansionTile( + // title: Text( + // 'Click to expand more information', + // style: Theme.of(context).textTheme.subtitle1, + // ), + // children: [ + // // Guardian Information + // _buildSectionTitle( + // context, 'Guardian Information'), + // _buildEditableField( + // 'Guardian Name', userPerson.guardian_name, + // (value) { + // userPerson.guardian_name = value; + // }, + // validator: (value) => value!.isEmpty + // ? 'Guardian name is required' + // : null), + // _buildEditableField( + // 'Guardian Contact Number', + // userPerson.guardian_contact_number + // ?.toString() ?? + // '', (value) { + // userPerson.guardian_contact_number = + // int.tryParse(value); + // }, validator: _validatePhone), + + // const SizedBox(height: 20), + + // // O/L Results Section + // _buildSectionTitle(context, 'O/L Results'), + // // _buildEditableField('Subject 1', userPerson.ol_subject1, + // // (value) { + // // userPerson.ol_subject1 = value; + // // }), + // // _buildEditableField('Subject 2', userPerson.ol_subject2, + // // (value) { + // // userPerson.ol_subject2 = value; + // // }), + // // _buildEditableField('Subject 3', userPerson.ol_subject3, + // // (value) { + // // userPerson.ol_subject3 = value; + // // }), + // // _buildEditableField( + // // 'Other Results', userPerson.ol_other_results, + // // (value) { + // // userPerson.ol_other_results = value; + // // }), + + // const SizedBox(height: 20), + + // // Add other expandable sections here if needed + // ], + // ), // const SizedBox(height: 20), // _buildSectionTitle(context, 'Professional Information'), @@ -391,11 +392,11 @@ class _StudentCreateState extends State { // _buildEditableTextArea('Comments', userPerson.notes, (value) { // userPerson.notes = value; // }), - const SizedBox(height: 40), - _buildSaveButton( - isDistrictsDataLoaded, - isOrganizationsDataLoaded, - isAvinyaTypesDataLoaded), + // const SizedBox(height: 40), + // _buildSaveButton( + // isDistrictsDataLoaded, + // isOrganizationsDataLoaded, + // isAvinyaTypesDataLoaded), ], ), ), @@ -407,14 +408,49 @@ class _StudentCreateState extends State { // Step 2: File Upload Step( title: Text('Upload Files'), - content: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildSectionTitle(context, 'File Upload'), - _buildFileUploadWidget('Upload Profile Photo'), - _buildFileUploadWidget('Upload NIC Copy'), - _buildFileUploadWidget('Upload O/L Certificate'), - ], + content: SingleChildScrollView( + padding: const EdgeInsets.all(16.0), + child: Center( + child: SizedBox( + width: 800, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // _buildSectionTitle(context, 'File Upload'), + // GridView inside SingleChildScrollView + GridView.builder( + shrinkWrap: true, // Avoid infinite size issue + physics: NeverScrollableScrollPhysics(), + gridDelegate: + SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, // 2 items per row + crossAxisSpacing: 16.0, + mainAxisSpacing: 16.0, + childAspectRatio: + 1.5, // Adjust the aspect ratio to take up more space + ), + itemCount: 8, + itemBuilder: (context, index) { + List documentTypes = [ + 'NIC Front', + 'NIC Back', + 'Birth Certificate Front', + 'Birth Certificate Back', + 'O/L Certificate', + 'A/L Certificate', + 'Additional Certificate', + 'Another Document' + ]; + + return FileUploadWidget( + documentType: documentTypes[index], + ); + }, + ), + ], + ), + ), + ), ), isActive: _currentStep >= 1, ), @@ -425,20 +461,48 @@ class _StudentCreateState extends State { // Navigate to the next step void _nextStep() { - if (_currentStep == 0) { + bool isEnabled = isDistrictsDataLoaded && + isOrganizationsDataLoaded && + isAvinyaTypesDataLoaded; + print('is enabled:${isEnabled}'); + if (_currentStep == 0 && isEnabled) { if (_formKey.currentState!.validate()) { _formKey.currentState!.save(); + createPerson(context, userPerson); setState(() { _currentStep += 1; }); } - } else if (_currentStep < 1) { + } else if (_currentStep < 1 && isEnabled) { setState(() { _currentStep += 1; }); } } + // Widget _buildSaveButton(bool isDistrictsDataLoaded, + // bool isOrganizationsDataLoaded, bool isAvinyaTypesDataLoaded) { + // bool isEnabled = isDistrictsDataLoaded && + // isOrganizationsDataLoaded && + // isAvinyaTypesDataLoaded; + // print('is enabled:${isEnabled}'); + + // return Center( + // child: ElevatedButton( + // onPressed: isEnabled + // ? () { + // if (_formKey.currentState!.validate()) { + // _formKey.currentState!.save(); + // // Save userPerson changes + // createPerson(context, userPerson); + // } + // } + // : null, + // child: const Text('Create Student & Continue'), + // ), + // ); + // } + // Navigate to the previous step void _previousStep() { if (_currentStep > 0) { @@ -448,23 +512,6 @@ class _StudentCreateState extends State { } } - // Mock function for file upload widget - Widget _buildFileUploadWidget(String label) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Row( - children: [ - ElevatedButton( - onPressed: () { - // Logic to handle file upload - }, - child: Text('Upload $label'), - ), - ], - ), - ); - } - String? _validateEmail(String? value) { if (value == null || value.isEmpty) { return 'Email is required'; @@ -855,29 +902,6 @@ class _StudentCreateState extends State { .toList(); } - Widget _buildSaveButton(bool isDistrictsDataLoaded, - bool isOrganizationsDataLoaded, bool isAvinyaTypesDataLoaded) { - bool isEnabled = isDistrictsDataLoaded && - isOrganizationsDataLoaded && - isAvinyaTypesDataLoaded; - print('is enabled:${isEnabled}'); - - return Center( - child: ElevatedButton( - onPressed: isEnabled - ? () { - if (_formKey.currentState!.validate()) { - _formKey.currentState!.save(); - // Save userPerson changes - createPerson(context, userPerson); - } - } - : null, - child: const Text('Create Student'), - ), - ); - } - Widget _buildDateOfBirthField(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), diff --git a/campus/frontend/lib/avinya/enrollment/pubspec.yaml b/campus/frontend/lib/avinya/enrollment/pubspec.yaml index 1e2b4e2b..ce8bd2df 100644 --- a/campus/frontend/lib/avinya/enrollment/pubspec.yaml +++ b/campus/frontend/lib/avinya/enrollment/pubspec.yaml @@ -36,6 +36,9 @@ dependencies: month_year_picker: ^0.3.0+1 oktoast: ^3.4.0 fl_chart: ^0.60.0 + dotted_border: ^2.0.0+1 + image_picker: ^1.0.8 + file_picker: ^5.2.10 dev_dependencies: flutter_lints: ^2.0.1 diff --git a/campus/frontend/linux/flutter/generated_plugin_registrant.cc b/campus/frontend/linux/flutter/generated_plugin_registrant.cc index 6adbd2c4..c259cda9 100644 --- a/campus/frontend/linux/flutter/generated_plugin_registrant.cc +++ b/campus/frontend/linux/flutter/generated_plugin_registrant.cc @@ -6,10 +6,14 @@ #include "generated_plugin_registrant.h" +#include #include #include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); + file_selector_plugin_register_with_registrar(file_selector_linux_registrar); g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); diff --git a/campus/frontend/linux/flutter/generated_plugins.cmake b/campus/frontend/linux/flutter/generated_plugins.cmake index f32b910e..7c9fef0b 100644 --- a/campus/frontend/linux/flutter/generated_plugins.cmake +++ b/campus/frontend/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + file_selector_linux url_launcher_linux window_size ) diff --git a/campus/frontend/macos/Flutter/GeneratedPluginRegistrant.swift b/campus/frontend/macos/Flutter/GeneratedPluginRegistrant.swift index ea440b1c..a7c59bdd 100644 --- a/campus/frontend/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/campus/frontend/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,6 +5,7 @@ import FlutterMacOS import Foundation +import file_selector_macos import flutter_appauth import package_info_plus_macos import path_provider_foundation @@ -13,6 +14,7 @@ import url_launcher_macos import window_size func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FlutterAppauthPlugin.register(with: registry.registrar(forPlugin: "FlutterAppauthPlugin")) FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) diff --git a/campus/frontend/pubspec.yaml b/campus/frontend/pubspec.yaml index 853e39d4..a89770b3 100644 --- a/campus/frontend/pubspec.yaml +++ b/campus/frontend/pubspec.yaml @@ -61,6 +61,9 @@ dependencies: qr_code_scanner: ^1.0.1 flutter_date_range_picker: ^0.0.14 fl_chart: 0.60.0 + dotted_border: ^2.0.0+1 + image_picker: ^1.0.8 + file_picker: ^5.2.10 pdf: ^3.6.4 month_year_picker: ^0.3.0+1 diff --git a/campus/frontend/windows/flutter/generated_plugin_registrant.cc b/campus/frontend/windows/flutter/generated_plugin_registrant.cc index 7a1ff3b7..cd2d5c19 100644 --- a/campus/frontend/windows/flutter/generated_plugin_registrant.cc +++ b/campus/frontend/windows/flutter/generated_plugin_registrant.cc @@ -6,10 +6,13 @@ #include "generated_plugin_registrant.h" +#include #include #include void RegisterPlugins(flutter::PluginRegistry* registry) { + FileSelectorWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FileSelectorWindows")); UrlLauncherWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("UrlLauncherWindows")); WindowSizePluginRegisterWithRegistrar( diff --git a/campus/frontend/windows/flutter/generated_plugins.cmake b/campus/frontend/windows/flutter/generated_plugins.cmake index fc786d6b..a22fdb08 100644 --- a/campus/frontend/windows/flutter/generated_plugins.cmake +++ b/campus/frontend/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + file_selector_windows url_launcher_windows window_size )