Commit 29665037 authored by Sai Srinivas's avatar Sai Srinivas
Browse files

30-07-2025 By Sai Srinivas

CRM Module
parent 56ca3566
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="close">
<path fill="none" d="M0 0h24v24H0V0z"></path>
<path d="M18.3 5.71c-.39-.39-1.02-.39-1.41 0L12 10.59 7.11 5.7c-.39-.39-1.02-.39-1.41 0-.39.39-.39 1.02 0 1.41L10.59 12 5.7 16.89c-.39.39-.39 1.02 0 1.41.39.39 1.02.39 1.41 0L12 13.41l4.89 4.89c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L13.41 12l4.89-4.89c.38-.38.38-1.02 0-1.4z"></path>
</svg>
\ No newline at end of file
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="20" cy="20" r="20" fill="white"/>
<path d="M26.4376 15.7071C26.8281 15.3166 26.8281 14.6834 26.4376 14.2929C26.0471 13.9024 25.4139 13.9024 25.0234 14.2929L25.7305 15L26.4376 15.7071ZM13 26.7305C13 27.2828 13.4477 27.7305 14 27.7305L23 27.7305C23.5523 27.7305 24 27.2828 24 26.7305C24 26.1782 23.5523 25.7305 23 25.7305L15 25.7305L15 17.7305C15 17.1782 14.5523 16.7305 14 16.7305C13.4477 16.7305 13 17.1782 13 17.7305L13 26.7305ZM25.7305 15L25.0234 14.2929L13.2929 26.0234L14 26.7305L14.7071 27.4376L26.4376 15.7071L25.7305 15Z" fill="#4CAF50"/>
</svg>
......@@ -354,6 +354,7 @@ class Addnewleadsandprospectsprovider extends ChangeNotifier {
set productRows(value) {
_productRows = value;
productsEmptyError = "";
notifyListeners();
}
......@@ -369,6 +370,7 @@ class Addnewleadsandprospectsprovider extends ChangeNotifier {
String? TelephoneError = "";
String? mobileError = "";
String? addressError = "";
String? productsEmptyError = "";
String? designationError = "";
String? taxesError = "";
String? SpecialNoteError = "";
......@@ -764,6 +766,7 @@ class Addnewleadsandprospectsprovider extends ChangeNotifier {
districtsError = "";
subLocError = "";
leadStatusError = "";
productsEmptyError = "";
notifyListeners();
}
......@@ -836,7 +839,13 @@ class Addnewleadsandprospectsprovider extends ChangeNotifier {
if(mobileController.text.trim().isEmpty){
mobileError = "Please enter Mobile Number";
isValid = false;
}else{
if(mobileController.text.length<10){
mobileError = "Please enter 10 digits";
isValid = false;
}
}
// if(designationController.text.trim().isEmpty){
// designationError = "Please enter Designation";
// isValid = false;
......@@ -849,11 +858,11 @@ class Addnewleadsandprospectsprovider extends ChangeNotifier {
bool validateStep2(){
bool isValid = true;
// if(alternateMobileController.text.trim().isEmpty){
// AlternatemobileError = "";
// isValid = false;
//
// }
if(alternateMobileController.text.trim().isNotEmpty && alternateMobileController.text.length<10){
AlternatemobileError = "Please enter 10 digits";
isValid = false;
}
// if(telephoneController.text.trim().isEmpty){
// isValid = false;
//
......@@ -902,6 +911,10 @@ class Addnewleadsandprospectsprovider extends ChangeNotifier {
addressError = "Please Enter address";
isValid = false;
}
if(productRows.isEmpty || _productRows.isEmpty){
productsEmptyError = "Please Add min. one Product";
isValid = false;
}
notifyListeners();
return isValid;
}
......
import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
......@@ -8,6 +9,7 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:generp/Models/crmModels/crmLeadDetailsGenerateQuotationViewResponse.dart';
import 'package:generp/Models/crmModels/crmSelectedProductDetailsResponse.dart';
import 'package:generp/screens/LoginScreen.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';
import 'package:path_provider/path_provider.dart';
......@@ -25,6 +27,7 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
final GlobalKey webViewKey = GlobalKey();
var dl = DownloadManager();
bool _buttonsLoading = false;
ProductsData? _selectedProductsDeatilsData;
TextEditingController addEditProductPriceController = TextEditingController();
TextEditingController addEditQuantityController = TextEditingController();
......@@ -40,8 +43,16 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
List<Map<String, dynamic>> get productRows => _productRows;
bool get buttonsLoading => _buttonsLoading;
set buttonsLoading(bool value){
_buttonsLoading = value;
notifyListeners();
}
set productRows(value) {
_productRows = value;
productRowsError = "";
notifyListeners();
}
......@@ -50,6 +61,7 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
String? mailIdError = "";
String? mobileError = "";
String? subjectsError = "";
String? productRowsError = "";
String? taxesError = "";
String? SpecialNoteError = "";
String? forError = "";
......@@ -98,6 +110,7 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
set selectedTaxes(String? value){
_selectedTaxes = value;
taxesError = "";
notifyListeners();
}
......@@ -170,7 +183,7 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
if (index >= 0 && index < leadProductsList.length) {
leadProductsList[index] = updatedProduct;
_productRows[index] = {
"product_id": updatedProduct.productId!,
"product_id": updatedProduct.productId,
"price": updatedProduct.price,
"qty": updatedProduct.qty,
"net_price": updatedProduct.prodTotalPrice,
......@@ -190,11 +203,18 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
notifyListeners();
}
void preFillFormForEdit(LeadProducts product) {
checkDropdownReset();
selectedLeadProducts = product;
selectedAddEditLeadProductId = product.id;
selectedAddEditLeadProductName = product.productName;
void preFillFormForEdit(LeadProducts product,int index) {
final newprod = product;
selectedProducts = productsList.firstWhere(
(p) => p.id == newprod.productId,
orElse: () => Products(id: '', name: 'Unknown'),
);
// selectedLeadProducts = product;
selectedAddEditProductId = product.productId;
selectedAddEditProductName = product.productName;
addEditProductPriceController.text = product.price?.toString() ?? '';
addEditQuantityController.text = product.qty?.toString() ?? '';
addEditTotalAmountController.text =
......@@ -382,6 +402,11 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
quotation_type,
) async {
try {
if(!validateform()){
return;
}
_buttonsLoading = true;
notifyListeners();
final prov = Provider.of<HomescreenNotifier>(context, listen: false);
final data = await ApiCalling.crmLeadDetailsGenerateQuotationSubmitAPI(
prov.empId,
......@@ -399,6 +424,7 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
);
if (data != null) {
if (data.error == "0") {
_buttonsLoading = false;
_quotationFilePath = data.quoteFilepath!;
if (quotation_type == "genquotedown") {
String suggestedFilename = getUniqueFilename('quotation', 'pdf');
......@@ -419,9 +445,17 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
toast(context, data.message);
resetForm();
notifyListeners();
} else {}
} else {}
} else {
_buttonsLoading = false;
notifyListeners();
}
} else {
_buttonsLoading = false;
notifyListeners();
}
} catch (e, s) {
_buttonsLoading = false;
notifyListeners();
print("Error: $e, Stack: $s");
}
}
......@@ -621,6 +655,50 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
notifyListeners();
}
bool validateform(){
bool isValid = true;
if(mailIdController.text.trim().isEmpty){
mailIdError = "Please Enter Email ID";
isValid = false;
}
if(mobileController.text.trim().isEmpty){
mobileError = "Please Enter Mobile Number";
isValid = false;
}else{
if(mobileController.text.length<10){
mobileError = "Mobile Number should be 10 digits";
isValid = false;
}
}
if(subjectsController.text.isEmpty){
subjectsError = "Please Enter Subject";
isValid = false;
}
if(productRows.isEmpty||_productRows.isEmpty){
productRowsError = "Please Add Min. 1 Product";
isValid = false;
}
if(_selectedTaxes==null||_selectedTaxes==""){
taxesError = "Please select a value";
isValid = false;
}
if(SpecialNoteController.text.trim().isEmpty){
SpecialNoteError = "Please Enter a Note";
isValid = false;
}
if(forController.text.trim().isEmpty){
forError = "Please Enter FOR";
isValid = false;
}
if(paymentTermsController.text.trim().isEmpty){
paymentTermsError = "Please Enter Terms";
isValid = false;
}
_buttonsLoading = false;
notifyListeners();
return isValid;
}
void resetForm() {
checkDropdownReset();
_productRows.clear();
......@@ -669,6 +747,7 @@ class Crmgeneratequotationprovider extends ChangeNotifier {
mailIdError = "";
mobileError = "";
subjectsError = "";
productRowsError = "";
taxesError = "";
SpecialNoteError = "";
forError = "";
......
......@@ -33,8 +33,22 @@ class followUpUpdateProvider extends ChangeNotifier {
DateTime? _date;
String? _formattedDate;
String? _formattedDateToSend;
String? _dateError;
String? followupError;
String? followupFeedbackError;
String? leadStatusError;
String? appStatusError;
String? nextAppDateError;
String? nextAppType;
String? noteError;
String? orderStatusError;
String? competitorError;
String? reasonError;
String? get formattedDateToSend => _formattedDateToSend;
bool get submitLoading => _submitLoading;
TimeOfDay get selectedTime => _selectedTime;
......@@ -60,31 +74,37 @@ class followUpUpdateProvider extends ChangeNotifier {
set selectedFollowupType(String? value) {
_selectedFollowupType = value;
followupError = null;
notifyListeners();
}
set selectedLeadStatus(String? value) {
_selectedLeadStatus = value;
leadStatusError = null;
notifyListeners();
}
set nextAppointmentStatus(String? value) {
_nextAppointmentStatus = value;
appStatusError = null;
notifyListeners();
}
set selectNextAppointmentType(String? value) {
_selectNextAppointmentType = value;
nextAppType = null;
notifyListeners();
}
set selectOrderStatus(String? value) {
_selectOrderStatus = value;
orderStatusError = null;
notifyListeners();
}
set selectedCompetitor(String? value) {
_selectedCompetitor = value;
competitorError = null;
notifyListeners();
}
......@@ -109,11 +129,13 @@ class followUpUpdateProvider extends ChangeNotifier {
_formattedDate = value;
nextAppointmentDateController.text = _formattedDate!;
_dateError = null;
nextAppDateError = null;
notifyListeners();
}
set dateError(value) {
_dateError = value;
nextAppDateError = value;
notifyListeners();
}
......@@ -145,6 +167,10 @@ class followUpUpdateProvider extends ChangeNotifier {
[mode]
) async {
try {
if(!valid()){
return;
}
_submitLoading = true;
notifyListeners();
final prov = Provider.of<HomescreenNotifier>(context, listen: false);
......@@ -162,7 +188,7 @@ class followUpUpdateProvider extends ChangeNotifier {
competitor,
reasonController.text,
leadStatus,
nextAppointmentDateController.text,
_formattedDateToSend,
appointmentType,
sms,
noteController.text,
......@@ -187,9 +213,78 @@ class followUpUpdateProvider extends ChangeNotifier {
}
}
bool valid(){
followupError = null;
followupFeedbackError = null;
leadStatusError = null;
appStatusError = null;
nextAppDateError = null;
nextAppType = null;
noteError = null;
orderStatusError = null;
competitorError = null;
reasonError = null;
bool isValid = true;
if(_selectedFollowupType==null||_selectedFollowupType==""){
followupError = "Please select Followup Type";
isValid = false;
}
if(followUpFeedbackController.text.trim().isEmpty){
followupFeedbackError = "Please enter Feedback";
isValid = false;
}
if(_selectedLeadStatus==null||_selectedLeadStatus==""){
leadStatusError = "Please Select Lead Status";
isValid = false;
}
if(_nextAppointmentStatus==null||_nextAppointmentStatus==""){
appStatusError = "Please select a value";
isValid = false;
}
if(nextAppointmentStatus=="Next Appointment"){
if(nextAppointmentDateController.text.trim().isEmpty){
nextAppDateError = "Please Enter Date";
isValid = false;
}
if(_selectNextAppointmentType==null||_selectNextAppointmentType==""){
nextAppType = "Please select Appointment Type";
isValid = false;
}
if(noteController.text.trim().isEmpty){
noteError = "Enter Note";
isValid = false;
}
}else if(nextAppointmentStatus=="Update Order Status"){
if(_selectOrderStatus==null||_selectOrderStatus==""){
orderStatusError = "Please Select Order Status";
isValid = false;
}
if(selectOrderStatus=="Order Lost"){
if(_selectedCompetitor==null||_selectedCompetitor==""){
competitorError = "Please Select Competitor";
isValid = false;
}
}else if(selectOrderStatus=="No Requirement"){
if(reasonController.text.trim().isEmpty){
reasonError = "Please Enter reason";
isValid = false;
}
}
}
_submitLoading = false;
notifyListeners();
return isValid;
}
void setDate(DateTime newDate) {
_date = newDate;
_formattedDate = DateFormat('yyyy-MM-dd').format(newDate);
// _formattedDate = DateFormat('yyyy-MM-dd').format(newDate);
_formattedDate = DateFormat('d MMM yyyy').format(newDate);
_formattedDateToSend = DateFormat('yyyy-MM-dd').format(newDate);
nextAppointmentDateController.text = _formattedDate!;
_dateError = null;
notifyListeners();
......@@ -272,11 +367,13 @@ class followUpUpdateProvider extends ChangeNotifier {
),
),
),
Expanded(
flex: 3,
child: CupertinoDatePicker(
dateOrder: DatePickerDateOrder.dmy,
initialDateTime: _date ?? DateTime.now(),
minimumDate: DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day),
dateOrder: DatePickerDateOrder.dmy,
mode: CupertinoDatePickerMode.date,
use24hFormat: true,
showDayOfWeek: true,
......@@ -292,14 +389,28 @@ class followUpUpdateProvider extends ChangeNotifier {
);
}
onFollowUpChanged(value) {}
onFollowUpChanged(value) {
onNoteChanged(value) {}
followupFeedbackError = null;
notifyListeners();
}
onNoteChanged(value) {
noteError = null;
notifyListeners();
}
onReasonChanged(value) {}
onReasonChanged(value) {
reasonError = null;
notifyListeners();
}
void resetForm(){
nextAppointmentDateController.clear();
_formattedDateToSend = null;
_formattedDate = null;
_date = null;
followUpFeedbackController.clear();
noteController.clear();
reasonController.clear();
......@@ -309,6 +420,16 @@ class followUpUpdateProvider extends ChangeNotifier {
_selectNextAppointmentType = null;
_selectOrderStatus = null;
_selectedCompetitor = null;
followupError = null;
followupFeedbackError = null;
leadStatusError = null;
appStatusError = null;
nextAppDateError = null;
nextAppType = null;
noteError = null;
orderStatusError = null;
competitorError = null;
reasonError = null;
notifyListeners();
}
}
......@@ -18,4 +18,13 @@ class AppColors {
static Color text_field_color = Color(0xFFF0F4F5);
static Color overlay_box_color = Color(0xFFE6F6FF);
static Color ERP_text_color = Color(0xFF2D357F);
static Color requested_text_color = Color(0xFF1487C9);
static Color rejected_text_color = Color(0xFFEF3739);
static Color approved_text_color = Color(0xFF4CB443);
static Color processed_text_color = Color(0xFFFFB600);
static Color requested_bg_color = Color(0xFFE6F6FF);
static Color rejected_bg_color = Color(0xFFFFF5F5);
static Color approved_bg_color = Color(0xFFE9FFE8);
static Color processed_bg_color = Color(0xFFEFFF8E5);
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -135,7 +135,7 @@ class _AddleadproductscreenState extends State<Addleadproductscreen> {
(ord) => DropdownMenuItem<Products>(
value: ord,
child: Text(
"(Product Name: ${ord.name})",
"${ord.name}",
style: const TextStyle(
fontSize: 14,
),
......
......@@ -7,6 +7,7 @@ import 'package:flutter/services.dart';
import 'package:flutter_svg/svg.dart';
import 'package:generp/Notifiers/crmProvider/addNewLeadsandProspectsProvider.dart';
import 'package:generp/Utils/app_colors.dart';
import 'package:generp/Utils/commonServices.dart';
import 'package:generp/Utils/commonWidgets.dart';
import 'package:generp/Utils/dropdownTheme.dart';
import 'package:provider/provider.dart';
......@@ -597,6 +598,7 @@ class _AddleadsprospectsscreenState extends State<Addleadsprospectsscreen> {
borderRadius: BorderRadius.circular(16),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
InkResponse(
onTap: () async {
......@@ -833,6 +835,10 @@ class _AddleadsprospectsscreenState extends State<Addleadsprospectsscreen> {
),
),
],
if(provider.productsEmptyError!.trim().isNotEmpty)...[
errorWidget(context, provider.productsEmptyError)
]
],
),
),
......@@ -1233,21 +1239,26 @@ class _AddleadsprospectsscreenState extends State<Addleadsprospectsscreen> {
InkResponse(
onTap: () {
if (provider.validateStep3()) {
provider.crmAddNewLeadsAndProspectsAPIFunction(
context,
"",
provider.selectedEmployeesId,
provider.selectedSalutation,
provider.selectedDistrictId,
provider.selectedStatesId,
provider.selectedSegmentId,
provider.selectedSourcesId,
provider.selectedReferenceId,
provider.selectedReferenceId,
provider.selectedSubLocationId,
provider.selectedLeadStatus,
provider.getJsonEncodedProducts(),
);
if(provider.productRows.isNotEmpty){
provider.crmAddNewLeadsAndProspectsAPIFunction(
context,
"",
provider.selectedEmployeesId,
provider.selectedSalutation,
provider.selectedDistrictId,
provider.selectedStatesId,
provider.selectedSegmentId,
provider.selectedSourcesId,
provider.selectedReferenceId,
provider.selectedReferenceId,
provider.selectedSubLocationId,
provider.selectedLeadStatus,
provider.getJsonEncodedProducts(),
);
}else{
toast(context, "Add min. 1 product");
}
}
details.onStepContinue;
......
......@@ -252,7 +252,7 @@ class _AddProspectLeadsState extends State<AddProspectLeads> {
>(
value: ord,
child: Text(
"(Product Name: ${ord.name})",
"${ord.name}",
style: const TextStyle(
fontSize: 14,
),
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment