When I click the detail row , it disappear , and a white background appear , I wonder what is the problem.

Note : I'm  working with a custom detail with list

 

Like 0

Like

2 comments

this is my code

 

define("StFriendAndFamilyNumbersDetail", ["StFriendAndFamilyDetailResources", "ConfigurationGrid", "ConfigurationGridGenerator",

    "ConfigurationGridUtilities", "StServiceViewModel", "css!StServiceDetailCSS"], function (resources) {

    var detailData =[];

    var isAddMode =false;

    var isFirstTime = true;

return {

    entitySchemaName: "StFriendAndFamilyDetail",

    mixins: {

        ConfigurationGridUtilities: "Terrasoft.ConfigurationGridUtilities"

    },

    attributes: {

        "StNameFilter": {

            "dataValueType": Terrasoft.DataValueType.TEXT

        },

        "IsEditable": {

            "dataValueType": Terrasoft.DataValueType.BOOLEAN,

            "type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,

            "value": false

        },

        "PageNumber": {

            "dataValueType": Terrasoft.DataValueType.INTERGER,

            "type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,

            "value": 0

        },

        "NumberOfRecords": {

            "dataValueType": Terrasoft.DataValueType.INTERGER,

            "type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,

            "value": 15

        }

    },

    methods: {

        sortColumn: this.Terrasoft.emptyFn,

        loadGridData: this.Terrasoft.emptyFn,

        loadFilter: function () {

            this.set("PageNumber", 0);

            var gridData = this.getGridData();

            if (gridData) {

                gridData.clear();

                this.set("IsDetailCollapsed", false);

                this.loadSearchItems(

                    this.get("StNameFilter"),

                    this.get("PageNumber"),

                    this.get("NumberOfRecords"),

                    gridData

                );

            }

        },

        loadMore: function () {

            var pageNumber = this.get("PageNumber");

            this.set("PageNumber", ++pageNumber);

            var gridData = this.getGridData();

            if (gridData) {

                this.loadSearchItems(

                    this.get("StNameFilter"),

                    this.get("PageNumber"),

                    this.get("NumberOfRecords"),

                    gridData

                );

            }

        },

        generateActiveRowControlsConfig: function (id, columnsConfig, rowConfig) {

            debugger;

            this.columnsConfig = columnsConfig;

            var gridLayoutItems = [];

            var currentColumnIndex = 0;

            this.Terrasoft.each(columnsConfig, function (columnConfig) {

                var columnName = columnConfig.key[0].name.bindTo;

                var column = this.getColumnByColumnName(columnName);

                var cellConfig = this.getCellControlsConfig(column);

                cellConfig = this.Ext.apply({

                    layout: {

                        colSpan: columnConfig.cols,

                        column: currentColumnIndex,

                        row: 0,

                        rowSpan: 1

                    }

                }, cellConfig);

            /*    if (cellConfig.name === "StServiceParams") {

                    this.set("ComboBoxCollection", new this.Terrasoft.Collection());

                    cellConfig.contentType = Terrasoft.ContentType.ENUM;

                    cellConfig = this.Ext.apply({

                        controlConfig: {

                            list: {

                                bindTo: "ComboBoxCollection"

                            },

                            prepareList: {

                                bindTo: "getComboBoxItems"

                            },

                            change: {

                                bindTo: "ontServiceParamsChange"

                            }

                        }

                    }, cellConfig);

                    cellConfig.enabled = true;

                }

                else {

                    cellConfig.enabled = false;

                }*/

                gridLayoutItems.push(cellConfig);

                currentColumnIndex += columnConfig.cols;

            }, this);

            var gridData = this.getGridData();

            var activeRow = gridData.get(id);

            var options = activeRow.values;

            activeRow.setOptions(options);

            var viewGenerator = this.Ext.create("Terrasoft.ViewGenerator");

            viewGenerator.viewModelClass = { prototype: this };

            var gridLayoutConfig = viewGenerator.generateGridLayout({

                name: this.name,

                items: gridLayoutItems

            });

            console.log(gridLayoutConfig);

            rowConfig.push(gridLayoutConfig);

        },

    

    /*    onSubmitDetail: function () {

            var selectedRows = this.get("SelectedRows");

            if (selectedRows && selectedRows.length > 0) {

                for (var i = 0; i < selectedRows.length; i++) {

                    var selectedItem = this.getGridData().collection.getByKey(selectedRows[i]);

                }

                debugger;

                // TODO selected items processing logic

            }

            else {

                this.showInformationDialog("There isn't any selected item");

            }

        },*/

        init: function (callback, scope) {

            this.set("PageNumber", 0);

            this.callParent([

                function () {

                    var gridData = this.getGridData();

                    if (gridData) {

                        gridData.clear();

                        this.set("IsDetailCollapsed", false);

                        this.loadSearchItems( null, this.get("PageNumber"),

                        this.get("NumberOfRecords"), gridData);

                    }

                    callback.call(scope);

                }, this

            ]);

        

        

            this.sandbox.subscribe("SendDetailData", function (arg) {

                    debugger;

                     detailData = arg.array;

                    this.UpdateRatePlanServices();

                }, this, ["SendDetailDataKey"]);

                

                

            this.sandbox.subscribe("GetDetailData", function (arg) {

                   debugger;

                   var gridData = this.getGridData();

                   var array=[];

        

                if(isFirstTime){

                    

                    isFirstTime=false;

                    

                    for (var i = 0; i < gridData.collection.items.length; i++) {

                           

                           var item = gridData.collection.items[i];

                           var obj={};

                        obj.Id = item.values.StId;

                        obj.PhoneNumber = item.values.StPhoneNumber;

                        obj.ContractId = item.values.StContractId;

                        

                        array.push(obj);

                           

                       }

                       

                    return array;

                    

                }else{

                    

                    return detailData;

                    

                }

                   

                    

           }, this, ["GetDetailDataKey"]);

        

        

        },

        onDetailCollapsedChanged: function () {

            this.callParent(arguments);

            if (!this.get("IsDetailCollapsed")) {

                this.set("PageNumber", 0);

                var gridData = this.getGridData();

                if (gridData) {

                    gridData.clear();

                    this.loadSearchItems( null, this.get("PageNumber"),

                    this.get("NumberOfRecords"), gridData);

                }

            }

        },

        loadSearchItems: function (nameFltr, pageNb, nbOfRecords, gridData) {

    

            debugger;

            var contractId = this.sandbox.publish("GetContractIDMessage", null, ["GetContractIDMessageKey"]);

            

            this.set("MaskId", Terrasoft.Mask.show({ timeout: 0 }));

            this.set("IsGridEmpty", true);

            this.set("IsGridLoading", true);

            this.set("IsGridDataLoaded", false);

            

            if(detailData == null || detailData == "" || detailData == []){

                

                var serviceConfig = {

                    serviceName: "StContractManagerService",

                    methodName: "GetFriendAndFamilyNumbers",

                    timeout: 120000,

                    data: { 

                        contractId: contractId

                    }

                };

                isAddMode = false;

            }else{

                

                var serviceConfig = {

                    serviceName: "StContractManagerService",

                    methodName: "ConstructFriendAndFamilyDetail",

                    timeout: 120000,

                    data: { 

                        array: JSON.stringify(detailData)

                    }

                };

                    isAddMode = true;

            }

            

            this.callService(serviceConfig, function (responseJson) {

                this.set("IsGridLoading", false);

                this.set("IsGridDataLoaded", true);

                if (!this.Ext.isEmpty(responseJson)) {

                    

                        if(!isAddMode){ 

                            var response = this.Ext.decode(responseJson.GetFriendAndFamilyNumbersResult);

                        }else{

                            var response = this.Ext.decode(responseJson.ConstructFriendAndFamilyDetailResult);

                        }

                        

                    if (response.success) {

                            console.log(response);

                        if (response.rowsAffected > 0) {

                            this.set("IsGridEmpty", false);

                            this.set("CanLoadMoreData", response.canShowMore);

                            var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {

                                rootSchemaName: "StFriendAndFamilyDetail",

                                rowViewModelClassName: "Terrasoft.StServiceViewModel"

                            });

                            esq.parseResponse(response, function (result) {

                                if (result.success) {

                                    console.log(result);

                                    var resultCollection = result.collection;

                                    resultCollection.each(function (item) {

                                    item.init(this);

                                    }, this);

                                    gridData.loadAll(result.collection);

                                    this.prepareResponseCollection(resultCollection);

                                    Terrasoft.Mask.hide(this.get("MaskId"));

                                    

                                    

                                }

                                else {

                                    this.showInformationDialog(result.errorInfo);

                                    Terrasoft.Mask.hide(this.get("MaskId"));

                                }

                            }, this);

                        }

                        else {

                            this.set("CanLoadMoreData", false);

                            Terrasoft.Mask.hide(this.get("MaskId"));

                        }

                    }

                    else {

                        this.set("CanLoadMoreData", false);

                        this.showInformationDialog(response.errorInfo.message);

                        Terrasoft.Mask.hide(this.get("MaskId"));

                    }

                }

            }, this);

        },

    

        UpdateRatePlanServices: function(){

            var gridData = this.getGridData();

                    if (gridData) {

                        gridData.clear();

                        this.set("IsDetailCollapsed", false);

                        this.loadSearchItems( null, this.get("PageNumber"),

                        this.get("NumberOfRecords"), gridData);

                    }

            },

    

        

        onActiveRowAction: function (buttonTag,primaryColumnValue) {

                debugger;

                switch (buttonTag) {

                case "someButton":

                //this.onSomeButtonClicked(primaryColumnValue);

                break;

                default:

                break;

                }

        },

                

    },

    messages: {

            "SendDetailData": {

                mode: Terrasoft.MessageMode.PTP,

                direction: Terrasoft.MessageDirectionType.SUBSCRIBE

            },

             "GetDetailData":

             {

                mode: Terrasoft.MessageMode.PTP,

                direction: Terrasoft.MessageDirectionType.SUBSCRIBE

            },

            "GetContractIDMessage": {

                mode: Terrasoft.MessageMode.PTP,

                direction: Terrasoft.MessageDirectionType.PUBLISH

            },

        },

    diff: /**SCHEMA_DIFF*/[

        {

            "operation": "merge",

            "name": "DataGrid",

            "parentName": "Detail",

            "values": {

                "className": "Terrasoft.ConfigurationGrid",

            //    "generator": "ConfigurationGridGenerator.generatePartial",

                "generateControlsConfig": { "bindTo": "generateActiveRowControlsConfig" },

                /*"changeRow": { "bindTo": "changeRow" },*/

                "multiSelect": true

            },

            "index": 0

        },

    {

                "operation": "merge",

                "name": "DataGrid",

                "values": {

                    "activeRowAction": {"bindTo": "onActiveRowAction"},

                    "activeRowActions": []

                    

                }

            },

            {

                "operation": "insert",

                "name": "DataGridActiveRowSomeButton",

                "parentName": "DataGrid",

                "propertyName": "activeRowActions",

                "values": {

                    "className": "Terrasoft.Button",

                    "style": Terrasoft.controls.ButtonEnums.style.GREEN,

                    "caption": "Details",

                    "tag": "someButton"

                }

            },

    

            

    

    ]

    /**SCHEMA_DIFF*/

};

});

 

Hello Mohamad!



To resolve this problem you should debug js client code. Here you can read additional information about debugging client code:

https://academy.bpmonline.com/documents/technic-sdk/7-13/client-code-de… 



If I got this right, method "generateActiveRowControlsConfig" triggers when user clicks on row, so you should pay an extra attention to it.



Best regards,

Alex

Show all comments

Hello,

I created a custom virtual detail and I fill it with data , I have column called 'url' and I want to make its value linkable .

Like 0

Like

2 comments

I made my text controls on the Edit page of a record clickable hyperlinks with the help of this question https://community.bpmonline.com/articles/creating-custom-web-link-field

Show all comments

Hi,

I developed a package that name is 'A', which I try to import on another instance of bpm'online .In new instance current Package id is set 'A'. if  any changes made gets reflected in the custom package (default) not in the new package.

 

Please give me your feedback..

Regards,

Sunitha

Like 0

Like

3 comments

Dear Sunitha,

Please check if your package is locked or unlocked (it will be gray if it is locked). Packages are usually locked if they were imported to another instance. 

currently import package is lock.how to unlock my package using new instance

 

Sunithaa.s,

They are locked because development process expects user to develop everything on dev- and then transfer changes to prod. They are locked because system expects they are finished and will not be changed anymore. You can read more about developing process on our Academy: https://academy.bpmonline.com/documents/technic-sdk/7-13/how-start-deve…

If this way is not suitable for you you can use version control to transfer the changes and be able to modify them later (see https://academy.bpmonline.com/documents/technic-sdk/7-13/transferring-c… for more information) 

Show all comments

I use the OData to extract the data. I need to get cases with the specific status from the CaseCollection. To do this I use the following Http-request:

https://company.bpmonline.com/0/ServiceModel/EntityDataService.svc/Case… eq guid'7e9f1204-f46b-1410-fb9a-0050ba5d6c38'.

But I recieve the "404 ERROR

1

Элемент коллекции с именем StatusId не найден " (The element  StatusId is not found").



But if I do https://company.bpmonline.com/0/ServiceModel/EntityDataService.svc/Case…;

it responses with 200 OK.



How to retrieve cases with the specific StatusId from CaseCollection? 

Like 0

Like

1 comments

Hello Timur,



The Status column in the Case table is the foreign key for CaseStatus table. Therefore, the correct syntax is the next: [Name_of_joinable_table / Name_of_column_for_linking_of_joinable_table].

In your example it will be: https://ticketland.bpmonline.com/0/ServiceModel/EntityDataService.svc/C… eq guid'7e9f1204-f46b-1410-fb9a-0050ba5d6c38'.

Show all comments

Hello Community, 

I was wondering if anyone has come across this request: 

 

A client would like to have multiple details that they can interact with and then one master detail showing all of the subsequent details and their records. 

 

Example 

Detail 1 has records: A, B and C

Detail 2 has records 1, 2 and 3

Detail 3 would have A, B, C, 1, 2 and 3 

Like 2

Like

1 comments

Dear Philip,

To accomplish the task you need to go through the following steps:

1. Create a view in the database.

2. Create the object in bpm'online linked to the view. Please note that the set of columns in the system should be the same as in the database view.

3. Link your custom detail to the object from p.2. 

Lisa

Show all comments

Hi,

I'm working on some development and came across this question. Please find below:

"When processing an order, check if the total amount of overdue payments/invoices exceeds $4,000. If it exceeds $4,000 then display this message: "Overdue payments/invoices = $X 100% advance payment required" and do not allow to save changes."
I understand that what needs to be possibly done is to over-ride the the save method, but I'm unable to find this in order to proceed further. I'm unable to find anything related to this in the development guide. Could you possibly help me out as to how to proceed?

Regards,

Sushanth.

File attachments

Like

5 comments

Dear Sushanth,

 

To fulfill such task you need to override the save method. This should look like this:

save: function() {
		//get the value of columns and check if number exceeds the limit
		var payments = this.get("Payments");
		var invoices = this.get("Invoices");
		//do the calculation
		var overdue = payments/invoices;
		if (overdue >= 4000) {
			this.showInformationDialog("Overdue payments/invoices = $X 100% advance payment required");
			return;
		} else {
		//if less then 4000, we proceed with save
			this.callParent(arguments);
		}
	}

 

 

Hope this will help.

 

Regards,

Anastasia

Hi Anastasia,

Thank you for that. I've worked ahead from there. Now I'm just stuck with regard to the query. I understand that one of my filters is hitting an error. Attaching my code (InvoicePageV2) with comments followed by my issue.

save: function() {
				var select = this.Ext.create("Terrasoft.EntitySchemaQuery", {
						rootSchemaName: "Invoice"
					});
				var contactid = this.get("Contact"); // I'm trying to retrieve the contact the invoice is associated with. 
				var amount = this.get("Amount");
				var paymentAmount = this.get("PaymentAmount");
				select.addAggregationSchemaColumn("Amount", Terrasoft.AggregationType.SUM, "TotalAmount");
				select.addAggregationSchemaColumn("PaymentAmount", Terrasoft.AggregationType.SUM, "TotalPaymentAmount");
                                //this filter seems to be the issue.
				var esqFirstFilter = select.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "Contact", contactid);
				var esqSecondFilter = select.createColumnFilterWithParameter(Terrasoft.ComparisonType.NOT_EQUAL, "PaymentStatus", "3fb932ea-f36b-1410-2691-00155d043205");
				select.filters.logicalOperation = Terrasoft.LogicalOperatorType.AND;
				select.filters.add("esqFirstFilter", esqFirstFilter);
				select.filters.add("esqSecondFilter", esqSecondFilter);
				select.getEntityCollection(function(response) {
						if (response.success) {
							var totalAmount = response.collection.getByIndex(0).get("TotalAmount") + amount;
							var totalPaymentAmount = response.collection.getByIndex(0).get("TotalPaymentAmount") + paymentAmount;
							var totalDue = totalAmount - totalPaymentAmount;
							if (totalDue > 4000) {
								this.showInformationDialog("Payment Overdue");
								return;
							}
							else {
								this.callParent(arguments);
							}
						} else {
							this.showInformationDialog("ESQ Error");
						}
					}, this);
			}

So is my retrieval of the contact associated with the invoice wrong? or am i going wrong somewhere else. Looking forward to hearing from you.

Regards,

Sushanth

Dear Sushanth,

You are correct rearding the filter causing the issue. It was not working, because you were passing the whole object to the filter, but not just Id. To overcome this, modify the way you retrieve contact var contactid =this.get("Contact").Id;

Also, please draw your attention to the fact, that ESQ is an asynchronious function and Save() is synchronious. Therefore, better to do the calculation prior save method, e.g. when contact is changed and set the value to some attribute, which can be accessed in save method.

Regards,

Anastasia

Hi Anastasia,

I've made the requirement work with some issues. Still testing it further but I want some review on if there is better way to do this. Find my code below:

				validateAccountOrContactFilling: function(callback, scope) {
					var account = this.get("Account");
					var contact = this.get("Contact");
					var result = {
						success: true
					};
					var select = this.Ext.create("Terrasoft.EntitySchemaQuery", {
						rootSchemaName: "Invoice"
					});
					var amount = this.get("Amount");
					if (amount === undefined) {
						amount = 0;
					}
					var paymentAmount = this.get("PaymentAmount");
					if (paymentAmount === undefined) {
						paymentAmount = 0;
					}
					select.addAggregationSchemaColumn("Amount", Terrasoft.AggregationType.SUM, "TotalAmount");
					select.addAggregationSchemaColumn("PaymentAmount", Terrasoft.AggregationType.SUM, "TotalPaymentAmount");
					var esqSecondFilter = select.createColumnFilterWithParameter(Terrasoft.ComparisonType.NOT_EQUAL,
							"PaymentStatus", "3fb932ea-f36b-1410-2691-00155d043205");
					var esqThirdFilter = select.createColumnFilterWithParameter(Terrasoft.ComparisonType.LESS, "DueDate", new Date());
					select.filters.logicalOperation = Terrasoft.LogicalOperatorType.AND;
					if (contact) {
						var esqFirstFilterContact = select.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
								"Contact", contact.value);
						select.filters.add("esqFirstFilterContact", esqFirstFilterContact);
					}
					else {
						var esqFirstFilterAccount = select.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
								"Account", account.value);
						select.filters.add("esqFirstFilterAccount", esqFirstFilterAccount);
					}
					select.filters.add("esqSecondFilter", esqSecondFilter);
					select.filters.add("esqThirdFilter", esqThirdFilter);
					select.getEntityCollection(function(response) {
							if (response.success) {
								var totalAmount = response.collection.getByIndex(0).get("TotalAmount") + amount;
								var totalPaymentAmount = response.collection.getByIndex(0).get("TotalPaymentAmount") + paymentAmount;
								var totalDue = totalAmount - totalPaymentAmount;
								if (totalDue > 4000) {
									this.showInformationDialog("Overdue payments/invoices = $" + totalDue + " 100% advance payment required");
									result.success = false;
									callback.call(scope || this, result);
								}//issue in this else bock.
								else {
									this.save();
									callback.call(scope || this, result);
								}
							} else {
								this.showInformationDialog("ESQ Error");
							}
						}, this);
				}

So when creating a new invoice, this script works perfectly - validation for due amount, validation for contact/account field and saving only when the due amount is less that 4000$. But when I modify the payment amount such that the due amount is less than 4000$, the callback function is causing a loop. I've tried replacing the callback with return, but it however doesn't work! Could you please suggest? Also, I did try overriding the save function, but that gave me other issues, so decided to replace this function!

Regards,

Sushanth.

Hi,

Alright. Debugged it and found out the issue. The save function I called - this.save() triggered a loop. I've fixed it now. Works well! Attaching my code.

validateAccountOrContactFilling: function(callback, scope) {
	var account = this.get("Account");
	var contact = this.get("Contact");
	var result = {
		success: true
	};
	var select = this.Ext.create("Terrasoft.EntitySchemaQuery", {
		rootSchemaName: "Invoice"
	});
	var amount = this.get("Amount");
	if (amount === undefined) {
		amount = 0;
	}
	var paymentAmount = this.get("PaymentAmount");
	if (paymentAmount === undefined) {
		paymentAmount = 0;
	}
	select.addAggregationSchemaColumn("Amount", Terrasoft.AggregationType.SUM, "TotalAmount");
	select.addAggregationSchemaColumn("PaymentAmount", Terrasoft.AggregationType.SUM, "TotalPaymentAmount");
	var esqSecondFilter = select.createColumnFilterWithParameter(Terrasoft.ComparisonType.NOT_EQUAL,
			"PaymentStatus", "3fb932ea-f36b-1410-2691-00155d043205");
	var esqThirdFilter = select.createColumnFilterWithParameter(Terrasoft.ComparisonType.LESS, "DueDate", new Date());
	select.filters.logicalOperation = Terrasoft.LogicalOperatorType.AND;
	if (contact) {
		var esqFirstFilterContact = select.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
				"Contact", contact.value);
		select.filters.add("esqFirstFilterContact", esqFirstFilterContact);
	}
	else {
		var esqFirstFilterAccount = select.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
				"Account", account.value);
		select.filters.add("esqFirstFilterAccount", esqFirstFilterAccount);
	}
	select.filters.add("esqSecondFilter", esqSecondFilter);
	select.filters.add("esqThirdFilter", esqThirdFilter);
	select.getEntityCollection(function(response) {
			if (response.success) {
				var totalAmount = response.collection.getByIndex(0).get("TotalAmount") + amount;
				var totalPaymentAmount = response.collection.getByIndex(0).get("TotalPaymentAmount") + paymentAmount;
				var totalDue = totalAmount - totalPaymentAmount;
				if (totalDue > 4000) {
					this.showInformationDialog("Overdue payments/invoices = $" + totalDue + " 100% advance payment required");
					result.success = false;
					callback.call(scope || this, result);
				}
				else {
					result.success = true;
					callback.call(scope || this, result);
				}
			} else {
				this.showInformationDialog("ESQ Error");
			}
		}, this);
}

Just let me know if there are any improvements you'd suggest.

Regards,

Sushanth.

Show all comments

I’m new to BPM’Online and I’m a little fuzzy on some terminology when it comes to setting up developer’s environments.  I have read all the PDFs I could find, but have questions.

I have setup a standalone dev/test server with BPM, IIS, SQL, Redis and SVN on it, all working as expected.

I also created a couple of developer’s pc with BPM, IIS, Redis, SQL and SVN client.

My newbie questions: 

·         I don’t completely understand when to create a workspace vs. just pointing a package to a SVN repository for each developer. Are both needed, what are the use case?

·         Should each developer have their own workspace and SVN repository? How are they used together?

·         Are workspaces only needed for cloud development? If not, do files get copied or created under a new IIS application folder when a workspace is created?

If anyone can share with me what is working for them in terms of setup or if they have any insights on setup or best practices I would greatly appreciate it.  Trying to get things right out of the gate.  Screen shots or images of your setup whould be great!

Thanks again.

 

https://academy.bpmonline.com/documents/technic-sdk/7-8/how-start-development

 https://academy.bpmonline.com/documents/technic-sdk/7-8/organizing-development-environment

 

Like

1 comments

Dear John,

Since your application is deployed on site, you can go two ways: 

Create a second (development) workspace on the same application or use different application(IIS + DB) for each developer.



No matter with way you go, you need to connect the application packages of each developer to the single SVN repository.



In this case, when developing within the same schema, the developer, who started first will be able to commit, however, in case another developer wants to use this schema, it will be blocked while the first one is working.



This will secure you from committing the same schema from two or more developers at once.

After you will be ready, you can upload changed from your developing workspace to the productive workspace.

Therefore, answering your question regarding workspaces: if your developers use separated applications(IIS+DB) then there is no need for workspaces. However, if they are working within one application (e.g. cloud) - workspaces are a good practise to distinguish development from productive environment.

Show all comments